基础

语言象限图

基础 - 图1

go 环境配置

变量 说明
GOPATH 定义go的项目目录,可以定义多个
GOROOT /usr/local/go go的安装路径

Go项目目录结构

重点关注src目录下的目录结构,因为目录下为我们编写项目的项目源码目录

开源项目 使用gin快速搭建WEB站点以及提供RestFull接口的目录结构如下

  1. src/github.com/ffhelicopter/tmm
  2. /api
  3. /handler
  4. /model
  5. /task
  6. /website
  7. main.go // 文件中定义了 package main

当我们运行go install main.go会在GOPATH/bin目录中生成可执行文件。

常用命令

  • go get 动态获取远程代码包(内部实际上分成了两步操作)
    • 从远程下载需要用到的包
    • 执行 go install
  • go install 内部实际上分成了两步操作
    • 生成可执行文件或者.a的包
    • 把编译好的结果移动到 bin/pkg 目录下
  • go build
    • 如果是普通包,不会产生任何文件
    • 如果需要在pkg下生成相应文件,就得执行 go install
    • 如果某个项目目录下有多个文件,你只想编译某个文件,使用 go build filename.go
    • 也可以指定编译输出的文件名 go build -o astaxie.exe
    • 会忽略目录下以 _/.开头的go文件
    • 如果源码针对不同的操作系统需要不同的处理,你可以根据不同的操作后缀来命名文件。
      • array_linux.go
      • array_windows.go
      • array_freebsd.go
  • go clean 用来移除当前源码包和关联源码包里编译生成的文件
  • go fmt 格式化代码文件
  • go test 自动读取源码目录下命名为 *_test.go的文件,生成并运行测试用的可执行文件。
  • go tool
    • go tool fix 用来修复以前老版本的代码到新版本
    • go tool vet directory | fiels 用来分析当前目录的代码是否都是正确的代码。
  • go generate 用于在编译前自动化生成某类代码
  • go doc
  • go version 查看go当前的版本
  • go env 查看当前go的环境变量
  • go list 列出当前全部安装的 package
  • go run 编译并运行 go 程序

开发工具

  • gocode
  • gopkgs
  • go-outline
  • go-symbols
  • guru
  • gorename
  • dlv
  • godef
  • goreturns
  • golin
  1. 有且仅有一个入口main
  2. 左大括号{必须与函数名同行
  3. Println()会自动换行
  4. 调用函数大部分都需要 import 包
  5. golang以包package为管理单位
  6. 每个文件必须先声明包
  7. 程序必须有一个main
  8. 导入包必须使用
  9. 变量声明后,必须使用
  1. // demo01
  2. package main
  3. import (
  4. "fmt"
  5. )
  6. func main() {
  7. fmt.Println("Hello go!")
  8. }

注释

Go也支持单行注释和块注释

  1. // Cap returns the capacity of the buffer's underlying byte slice,
  2. // that is, the total space allocated for the buffer's date
  3. /*
  4. Cap returns the capacity of the buffer's underlying byte slice,
  5. that is, the total space allocated for the buffer's date
  6. */
  7. // 函数之前的注释称为文档注释,应该以函数名同名开头
  8. // enterOrbit causes Superman to fly into low Earth orbit, a position
  9. // that presents several possibilitles for planet salvation.
  10. func enterOrbit() error {
  11. // do something
  12. }

map类型

  1. package main
  2. // 声明与初始化
  3. func main() {
  4. var m map[string]int //map声明后,需要使用make分配内存空间
  5. //m = make(map[string]int)
  6. m["a"] = 1
  7. //if v := m["b"]; v != nil { //b map取值时,返回v的默认零值
  8. if v, ok := m["b"]; ok {
  9. println(v)
  10. }
  11. }
  12. // map 循环赋值
  13. const N = 3
  14. func main() {
  15. m := make(map[int]*int)
  16. for i := 0; i < N; i++ {
  17. j := int(i)
  18. m[i] = &j
  19. }
  20. for _, v := range m {
  21. print(*v)
  22. }
  23. }

指针

  1. package main
  2. type S struct {
  3. m string
  4. }
  5. // 修改 A和B的行,确保输出 foo
  6. func f() *S {
  7. return __ //A
  8. }
  9. func main() {
  10. p := __ //B
  11. print(p.m) //print "foo"
  12. }
  13. // 修改后
  14. type S struct {
  15. m string
  16. }
  17. func f() *S {
  18. return new(S)//A
  19. }
  20. func main() {
  21. p := S{"foo"} //B
  22. print(p.m) //print "foo"
  23. }

接收输入

  1. func main() {
  2. var a int
  3. fmt.Printf("请输入变量a:")
  4. // 接收单个输入
  5. // fmt.Scanf("%d", &a)
  6. fmt.Scan(&a)
  7. fmt.Println("a =", a)
  8. var aa int
  9. var bb float64
  10. var cc string
  11. // 接收多个输入,按指定格式读取输入
  12. fmt.Println("please enter s string: ")
  13. fmt.Scanf("%d, %f, %s", &aa, &bb, &cc)
  14. fmt.Println("output", aa, bb, cc)
  15. /*
  16. please enter s string:
  17. 3333, 3.1111, hhhhhhhhhhhhhhhhh
  18. output 3333 3.1111 hhhhhhhhhhhhhhhhh
  19. */
  20. // 接收多个输入, 按空格分割读取输入
  21. fmt.Scanln(&aa, &bb, &cc)
  22. fmt.Println("output", aa, bb, cc)
  23. /*
  24. please enter s string:
  25. 300 3.4 haha
  26. output 300 3.4 haha
  27. please enter s string:
  28. 300, 3.4 , haha
  29. output 300
  30. */
  31. reader := bufio.NewReader(os.Stdin)
  32. data, _, _ := reader.ReadLine() // 返回字节切片
  33. fmt.Println(data)
  34. dataStr, _ := reader.ReadString('\n') // 指定结束字节符,接收输入;返回值为 string
  35. fmt.Println(dataStr)
  36. }

作用域

什么是作用域

声明语句的作用域是指源代码中可以有效使用这个名字的范围。

一个声明语句将程序的实体和一个名字关联:var name int =10,函数func Add(a, b int) int

不要将作用域与生命周期混为一谈。

1557452735661.png

类型判断

作用:类型断言表达式断言类型的变量X.(T)

  1. value, ok := variable.(type)
  2. // variable 必须是接口类型
  3. // type 是想要判断的类型

例如

  1. package main
  2. import "fmt"
  3. var container = []string("zero", "one", "two")
  4. func main() {
  5. value, ok := interface{}(container).([]string)
  6. fmt.Println(value, ok)
  7. }

deffer

类似于 pyton中的 try...exception的final

  1. func Clear() {
  2. fmt.Println("Clear resource.")
  3. }
  4. func TestDefer(t *testing.T) {
  5. defer Clear()
  6. fmt.Println("Start")
  7. }
  8. // output:
  9. // Start
  10. // Clear resource.
  11. func TestDefer(t *testing.T) {
  12. defer Clear()
  13. fmt.Println("Start")
  14. panic("err")
  15. }
  16. // output:
  17. // Start
  18. // Clear resource.
  19. // FAIL:
  20. // panicf: err [recovered]
  21. // panic: err