go开发需要了解的基本知识 - yellia1989/learn-doc GitHub Wiki

开发环境搭建

安装完go程序后,设置GOROOT和GOPATH(通过go env获取路径)。这样就可以开始开发了。注意,以后的开发就在GOPATH目录下进行。

go的包管理

module代表一个go功能(exe),它由许多个package组成。package中的所有文件中定义的变量,函数相互可见。一个项目中一般包含一个module,也可以包含多个。

go mod init

初始化一个module,生成一个go.mod文件,里面定义了module的module path(导入路径)和go版本号,module path标识了这个module的import path,package的import路径为module path+package name(文件夹名称)

使用package

mkdir morestrings
vim morestrings/reverse.go

// Package morestrings implements additional functions to manipulate UTF-8
// encoded strings, beyond what is provided in the standard "strings" package.
package morestrings

// ReverseRunes returns its argument string reversed rune-wise left to right.
func ReverseRunes(s string) string {
	r := []rune(s)
	for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 {
		r[i], r[j] = r[j], r[i]
	}
	return string(r)
}

vim main.go

import (
	"fmt"

	"github.com/user/hello/morestrings"
)

func main() {
	fmt.Println(morestrings.ReverseRunes("!oG ,olleH"))
}

go build / go install

go build会在当前目录生成hello

go install则会在GOPATH/bin目录下生成hello

go get会下载module中用到的远程package

参见hello module

变量初始化顺序

在一个go文件中, 初始化顺序规则:

  1. 引入的包
  2. 当前包中的变量常量
  3. 当前包的init
  4. main函数

注意:

  1. 当前go源文件中, 每一个被Import的包, 按其在源文件中出现顺序初始化。
  2. 如果当前包有多个init在不同的源文件中, 则按源文件名以字典序从小到大排序,小的先被执行到, 同一包且同一源文件中的init,则按其出现在文件中的先后顺序依次初始化; 当前包的package level变量常量也遵循这个规则; 其实准确来说,应是按提交给编译器的源文件名顺序为准,只是在提交编译器之前, go命令行工具对源文件名按字典序排序了。
  3. init只可以由go runtine自已调用, 我们在代码中不可以显示调用,也不可以被引用,如赋给a function variable。
  4. 包A 引入包B , 包B又引入包C, 则包的初始化顺序为: C -> B -> A
  5. 引入包,必须避免死循环,如 A 引 B , B引C, C引A.
  6. 一个包被其它多个包引入,如A -> B ->C 和 H -> I -> C , C被其它包引了2次, 但是注意包C只被初始化一次。
  7. 另一个大原则, 被依赖的总是先被初始化,当然呀。
  8. main包总是被最后一个初始化,这很好理解,因为它总是依赖别的包。

变量短声明

  1. 通过 变量名:= 表达式 来声明变量
  2. 只能使用在函数内部
  3. 重复使用短变量声明时,需要保证短变量声明语句中至少要声明一个新的变量,否则直接使用赋值语句 = 就可以了
  4. 在不同的作用域(if,for,switch),短变量声明语句会重新声明新的变量
  5. 在不同的作用域中,重复使用短变量声明时,如果变量名相同,会重新声明新的变量。
package main
import (
    "fmt"
    "os"
)
func main() {
    file, err := os.Open("file.go")
    if err != nil {
        file, err := os.Open("file2.go") // file 和 err 在 if 作用域中,是重新声明的两个变量
        fmt.Println(&file, &err)         // 通过两次输出的 file 和 err 的地址不同可以确认
    }
    fmt.Println(&file, &err)
}

类型转换

go是强类型语言,不能做像C/C++一样隐式的类型转换。

https://www.jianshu.com/p/bd2acab2a8e9

delve调试

break,continue,goto区别

https://www.kancloud.cn/liupengjie/go/570042