• Go语言系列一


    Go的应用:

    Docker

    Codis

    Glow类似于Hadoop

    Cockroach

    beego

    .......

    Go的中国社区

    Golang中国

    Go语言中文网

    Go语言环境搭建

    安装方式: Go源码安装,Go标准包安装,第三方工具安装,eg: GVM

    编辑器

    LiteIDE: Go语言开发工具 LiteIDE安装地址

    Goland

    Vscode + plugins (Code Runner)

    Atom + Package: go-plus

    /* !< Hello World */
    package main
    
    import "fmt"
    
    func main(){
        fmt.Print("Hello World!")
    }
    

    安装Go

    链接:http://docscn.studygolang.com/doc/install
    	 https://studygolang.com/dl
    	 https://golang.google.cn/dl/
    

    Go安装说明

    安装备用地址一

    安装备用地址二

    1569207934875

    linux安装

    1. 下载二进制包:go1.13.linux-amd64.tar.gz
    2. 将下载的二进制包解压至 /usr/local目录
    tar -C /usr/local -xzf go1.13.linux-amd64.tar.gz
    
    1. 将 /usr/local/go/bin 目录添加至PATH环境变量:
    export PATH=$PATH:/usr/local/go/bin
    //这个最好加在配置文件中eg: .profile 使用命令source $home/.profile执行
    
    1. notes:这些命令必须是作为根命令 or 通过sudo运行

    1569210187806

    Windows安装

    Windows 下可以使用 .msi 后缀安装包来安装。

    默认情况下 .msi 文件会安装在 c:Go 目录下。将 c:Goin (默认添加)目录添加到 Path 环境变量中。添加后需要重启命令窗口才能生效

    安装测试

    //创建工作目录 C:>Go_WorkSpace
    //test.go 测试代码
    //基本程序结构
    package main	//包,表明代码所在的模块(包)
    
    import "fmt"	//引入代码依赖
    
    //功能实现
    func main() {
    	fmt.Print("hello World!")
    }
    

    输出结果:

    1569207497024

    Go的优点

    Go提供了软件生命周期(开发、测试、部署、维护等等)的各个环节的工具,

    eg: go tool, gofmt, go test

    • 简洁 快速 安全
    • 并行 有趣 开源 生产力
    • 内存管理 数组安全 编译迅速
      • C 37 C++ 84 Go 25
      • 复合

    软件开发的新挑战

    1. 多核硬件架构
    2. 超大规模分布式计算集群
    3. Web模式导致的前所未有的开发规模和更新速度

    编写第一个Go程序

    开发环境构建

    GOPATH

    1. 在1.8版本前必须设置这个环境变量

    2. 1.8版本后(含1.8)如果没有设置使用默认值

      在Unix上默认为$HOME/go, 在windows上默认为%USERPROFILE%/go

      在Mac上GOPATH可以通过修改~/.bash_profile设置

      go version
      

      $GOPATH目录约定有三个子目录

      src  存放源代码(比如:.go .c .h .s等) GOPATH下的src目录就是接下来开发程序的主要目录,所有的源码都是放在这个目录下面,那么一般我们的做法就是一个目录一个项目
      
      pkg  编译时生成的中间文件(比如:.a)
      
      bin	 编译后生成的可执行文件(为了方便,可以把此目录加入到 $PATH 变量中,如果有多个gopath,那么使用${GOPATH//://bin:}/bin添加所有的bin目录)
      

    应用程序入口

    1. 必须是main包: package main
    2. 必须是main方法: func main()
    3. 文件名不一定是: main.go

    退出返回值

    1. Go中main函数不支持任何返回值
    2. 通过os.Exit来返回状态
    package main
    
    import (
    	"fmt"
    	"os"
    )
    
    func main() {
    	fmt.Println("Hello World!")
    	os.Exit(-1)
    }
    
    

    获取命令行参数

    1. main函数不支持传入参数

      func main(arg [] string)

      1. 在程序中直接通过os.Args获取命令行参数
    package main
    
    import (
    	"fmt"
    	"os"
    )
    
    func main() {
    	fmt.Println(os.Args)
    	if len(os.Args) > 1 { 
    		fmt.Println("Hello d!", os.Args[1])
    	}
    
    }
    
    /* !< output */
    jason951018@ubuntu:~/go_learning/src/ch1/main$ go build hello_world.go
    jason951018@ubuntu:~/go_learning/src/ch1/main$ ./hello_world xzp
    [./hello_world xzp]
    Hello d! xzp
    
    

    The master has failed more times than the beginner has tried.

    编写测试程序

    1. 源码文件以_test结尾: xxx_test.go

    2. 测试方法名以Test开头: func TestXXX(t *testing.T) {....}

      Test后的第一字母必须大写

    变量赋值

    与其它主要编程语言的差异

    1. 赋值可以进行自动类型推断
    2. 在一个赋值语句中可以对多个变量进行同时赋值

    常量定义

    与其它主要编程语言的差异

    快速设置连续值

    const (
    	Monday = iota + 1
        Tuesday
        Wednesday
        Thurday
        Friday
        Saturday
        Sunday
    )
    
    const (
    	Open = 1 << iota
        Close 
        Pending
    )
    

    基本数据类型

    bool
    string
    int		int8	int16	int32 	int64
    uint	uint8	uint16	uint32	uint64		uintptr
    byte	//alias for uint8
    rune	//alias for int32, represents a Unicode code point
    float32 	float64
    complex64 	complex128
    
    

    类型转换

    与其它主要编程语言的差异

    1. Go语言不允许隐式类型转换
    2. 别名和原有类型也不能进行隐式类型转换

    类型的预定义值

    1. math.MaxInt64
    2. math.MaxFloat64
    3. math.MaxUint32

    指针类型

    与其它主要编程语言的差异

    1. 不支持指针运算
    2. string是值类型, 其默认的初始化值为空字符串,而不是nil
    var s string
    if s == "" {
        
    }
    

    算术运算符

    A = 10 B = 20

    运算符 描述 实例
    + 相加 A+B 输出结果 30
    - 相减 A - B 输出结果 -10
    * 相乘 A * B 输出结果 200
    / 相除 B / A 输出结果2
    % 求余 B % A 输出结果0
    ++ 自增 A++ 输出结果11
    -- 自减 A--输出结果9

    Go语言没有前置的++, --, (++a)

    比较运算符

    运算符 描述 实例
    == 检查两个值是否相等,如果相等返回True,否则返回False (A == B) 为False
    != 检查两个值是否不相等,如果不相等返回True,否则返回False (A != B) 为True
    > 检查左边值是否大于右边值,如果是返回True,否则返回False (A > B) 为False
    < 检查左边值是否小于右边值,如果是返回True,否则返回False (A < B)为True
    >= 检查左边值是否大于等于右边值,如果是返回True,否则返回False (A >= B)为False
    <= 检查左边值是否小于等于右边值,如果是返回True, 否则返回False (A <= B)为True

    用==比较数组

    1. 相同维数且含有相同个数元素的数组才可以比较
    2. 每个元素都相同的才相等

    逻辑运算符

    运算符 描述 实例
    && 逻辑 AND 运算符,如果两边的操作数都是True,则条件True 否则为False (A && B)为False
    || 逻辑 OR 运算符, 如果两边的操作数有一个True,则条件True 否则为False (A || B)为True
    ! 逻辑 NOT 运算符, 如果条件为True,则逻辑NOT条件False,否则为True !(A && B)为True

    位运算符

    运算符 描述 实例
    & 按位与运算符"&"是双目运算符,其功能是参与运算的两数各对应的二进制相与 (A & B) 结果为12, 二进制为 0000 1100
    | 按位或运算符"|"是双目运算符,其功能是参与运算的两数各对应的二进位相或 (A | B)结果为61, 二进制为0011 1101
    ^ 按位异或运算符"^"是双目运算符,其功能是参与运算的两数各对应的二进制相异或, (A ^ B)结果为49, 二进制为0011 0001
    << 左移运算符"<<"是双目运算符,左移n位就是乘以2的n次方,其功能把"<<"左边的运算数的各二进位全部左移若干位,由 "<<"右边的数指定移动的位数,高位丢弃,低位补 A << 2结果为240 二进制为1111 0000
    >> 右移运算符">>"是双目运算符,右移n位就是除以2的n次方,其功能是把">>"左边的运算数的各二进位全部右移若干位,">>"右边的数指定移动的位数 A >> 2结果为15 二进制0000 1111

    位运算符

    与其它主要编程语言的差异

    &^按位置零

    1 &^ 0	-- 1
    1 &^ 1 	-- 0
    0 &^ 1  -- 0
    0 &^ 0 	-- 0
    //右边置1 值为0
    //右边置0 其值为左边的值
    

    循环

    与其它主要编程语言的差异

    Go语言仅支持循环关键字 for

    for j := 7; j <= 9; j++
    
    //while 条件循环
    //while (n < 5)
    
    n := 0
    for n < 5 {
        n++
        fmt.Println(n)
    }
    
    //无限循环
    //while (true)
    
    n := 0
    for {
        ...
    }
    

    if 条件

    if condition {
        // code to be executed if condition is true
    } else {
        // code to be executed if condition is false
    }
    
    if condition-1 {
        // code to be executed if condition-1 is true
    } else if condition-2 {
        // code to be executed if condition-2 is true
    } else {
        // code to be executed if both condition-1 and condition-2 are false
    }
    

    if 条件

    与其它主要编程语言的差异

    1. condition 表达式结果必须为布尔值
    2. 支持变量赋值:
    if var declaration;	condition {
        // code to be executed if condition is true
    }
    

    switch条件

    switch os := runtime.GOOS; os {
        case "darwin":
        	fmt.Println("OS x.")
        	//break
        case "linux":
        	fmt.Println("Linux.")
        default:
        	//freebsd, openbsd,
        	//plan9, windows...
        	fmt.Printf("%s.", os)
    }
    
    switch {
        case 0 <= Num && Num <= 3:
        	fmt.Printf("0-3")
        case 4 <= Num && Num <= 6:
        	fmt.Printf("4-6")
        case 7 <= Num && Num <= 9:
        	fmt.Printf("7-9")
    }
    

    switch条件

    与其它主要编程语言的差异

    1. 条件表达式不限制为常量或整数

    2. 单个case中,可以出现多个结果选项,使用逗号分隔

    3. 与C语言等规则相反,Go语言不需要用break来明确退出一个case

    4. 可以不设定switch之后的条件表达式,在此种情况下,整个switch结构

      与多个if...else...的逻辑作用等同

    数组的声明

    var a [3]int	//声明并初始化为默认零值
    a[0] = 1
    
    b := [3]int{1, 2, 3}	//声明同时初始化
    c := [2][2]int{{1, 2}, {3, 4}}	//多维数组初始化
    
    
    

    数组元素遍历

    与其它主要编程语言的差异

    func TestTravelArray(t *testing.T) {
        a := [...]int{1, 2, 3, 4, 5}	//不指定元素个数
        for idx, elem := range a {		//idx 索引, elem 元素
            fmt.Println(idx, elem)
        }
    }
    

    数组截取

    a[开始索引(包含),结束索引(不包含)] //左闭右开,原因数组索引从零开始

    a := [...]int{1, 2, 3, 4, 5}
    a[1:2]	//2
    a[1:3]	//2, 3
    a[1:len(a)]	//2, 3, 4, 5
    a[1:]	//2, 3, 4, 5
    a[:3]	//1, 2, 3
    

    切片内部结构

    切片声明

    var s0 []int
    s0 = append(s0, 1)
    
    s := []int{}
    
    s1 := []int{1, 2, 3}
    
    s2 := make([]int, 2, 4)
    /* []type, len, cap
    	其中len个元素会被初始化为默认零值,未初始化元素不可以访问
    */
    

    切片共享存储结构

    func TestSliceGrowing(t *testing.T) {
    	s := []int{}
    	for i := 0; i <= 10; i++ {
    		s = append(s, i)	//地址发生变化,创建新的存储地址
    		t.Log(len(s), cap(s))
    	}
    }
    /* !< output */
    === RUN   TestSliceGrowing
    --- PASS: TestSliceGrowing (0.00s)
        slice_test.go:26: 1 1
        slice_test.go:26: 2 2
        slice_test.go:26: 3 4
        slice_test.go:26: 4 4
        slice_test.go:26: 5 8
        slice_test.go:26: 6 8
        slice_test.go:26: 7 8
        slice_test.go:26: 8 8
        slice_test.go:26: 9 16
        slice_test.go:26: 10 16
        slice_test.go:26: 11 16
    PASS
    ok      command-line-arguments  0.002s
    
    func TestSliceShareMemory(t *testing.T) {
    	year := []string{"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep",
    		"Oct", "Nov", "Dec"}
    	Q2 := year[3:6]
    	t.Log(Q2, len(Q2), cap(Q2))
    	summer := year[5:8]
    	t.Log(summer, len(summer), cap(summer))
    	summer[0] = "Unkonw"
    	t.Log(Q2)
    	t.Log(year)
    }
    
    /* !< output */
    === RUN   TestSliceShareMemory
    --- PASS: TestSliceShareMemory (0.00s)
        slice_test.go:34: [Apr May Jun] 3 9
        slice_test.go:36: [Jun Jul Aug] 3 7
        slice_test.go:38: [Apr May Unkonw]
        slice_test.go:39: [Jan Feb Mar Apr May Unkonw Jul Aug Sep Oct Nov Dec]
    PASS
    ok      command-line-arguments  0.002s
    

    数组 vs 切片

    1. 容器是否可伸缩
    2. 是否可以进行比较
    func TestSliceComparing(t *testing.T) {
    	a := []int{1, 2, 3, 4}
    	b := []int{1, 2, 3, 4}
    	if a == b {
    		t.Log("equal")
    	}
    }
    
    /* !< output */
    slice_test.go:45:7: invalid operation: a == b (slice can only be compared to nil)
    

    Map 声明

    m := map[string]int{"one": 1, "two": 2, "three": 3}	//string key类型 int value类型
    
    m1 := map[string]int{}
    
    m1["one"] = 1
    
    m2 := make(map[string]int, 10, /*Initial Capacity */)
    //why not init len?
    //len 初始化为零值,map无法做到
    

    Map元素的访问

    与其它主要编程语言的差异

    在访问的Key不存在时,仍会返回零值,不能通过返回nil来判断元素时否存在

    if v , ok := m["four"]; ok {
        t.Log("four", v)
    } else {
        t.Log("Not existing")
    }
    

    Map遍历

    m := map[string]int{"one": 1, "two": 2, "three": 3}
    for k, v := range m {
        t.Log(k, v)
    }
    

    Map与工厂模式

    • Map的value可以是一个方法
    • 与Go的Dock type接口方式一起,可以方便的实现单一方法对象的工厂模式
    func TestMapWithFunValue(t *testing.T) {
    	m := map[int]func(op int) int{}
    	m[1] = func(op int) int { return op }
    	m[2] = func(op int) int { return op * op }
    	m[3] = func(op int) int { return op * op * op }
    	t.Log(m[1](2), m[2](2), m[3](2))
    }
    
    

    实现Set

    Go的内置集合中没有Set实现,可以map[type]bool

    1. 元素的唯一性
    2. 基本操作
      • 1> 添加元素
      • 2> 判断元素是否存在
      • 3> 删除元素
      • 4> 元素个数
    func TestMapForSet(t *testing.T) {
    	mySet := map[int]bool{}
    	mySet[1] = true
    	n := 3
    	if mySet[n] {
    		t.Logf("%d is existing", n)
    	} else {
    		t.Logf("%d is not existing", n)
    	}
    	mySet[3] = true
    	t.Log(len(mySet))
    	delete(mySet, 1)
    	n = 1
    	if mySet[n] {
    		t.Logf("%d is existing", n)
    	} else {
    		t.Logf("%d is not existing", n)
    	}
    }
    
  • 相关阅读:
    (转)干货|一次完整的性能测试,测试人员需要做什么?
    (转)JMeter性能测试-服务器资源监控插件详解
    【Android Apk重新签名报错re-sign.jar之解决方法】
    CrackMe_001
    判断二叉树是否是镜像对称
    顺时针打印矩阵
    利用前序遍历和中序遍历构造二叉树
    二叉树的四种遍历方式
    最长回文子串
    同步/异步/阻塞/非阻塞
  • 原文地址:https://www.cnblogs.com/xzpin/p/11440832.html
Copyright © 2020-2023  润新知