Day1 初学Go-基础知识 | 青训营笔记

73 阅读2分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 1 天

Golang特点

1.高性能、高并发 2.语法简单、学习曲线平缓 3.丰富的标准库 4.完善的工具链 5.静态链接 6.快速编译 7.跨平台 8.垃圾回收

开发环境配置

下载windows安装器:

studygolang.com/dl

修改一些环境变量

go env -w GOPATH=工作区路径(我的是D:\Golang\code)

这里可能会遇到warning: go env -w GOPATH=... does not override conflicting OS environment variable

image.png

原因是这个变量已配置,无法进行覆盖,所以需要手动去修改

windows => 设置 => 主页 => 关于 => 高级系统设置 => 环境变量 => GOPATH

配置代理

$ go env -w GO111MODULE=on
$ go env -w GOPROXY=https://goproxy.cn,direct

安装vscode插件

image (1).png

然后就可以编码使用了

使用go run filename.go运行程序或使用go build filename.go将程序编译成二进制文件

基本语法

  1. 变量声明

一般使用var进行变量的声明

var varName [varType] = value 
or
varName := value
such as:
var a, b, c int = 1, 2, 3
d := 4 

常量声明 => 将var改为const

const a int = 1
  1. 基本类型

字符串、布尔、浮点数、整数

  1. 分支结构

if和 python一样不需要括号,但必须跟大括号

if 1 == 1 {
    fmt.Println("pass")
}

switch分子结构

  var caseExample int = 3
  switch caseExample {
  case 1:
    fmt.Println("case 1")
  case 2:
    fmt.Println("case 2")
  case 3:
    fmt.Println("case 3")
  default:
    fmt.Println("case default")
  }
  switch {
  case caseExample > 5:
    fmt.Println("caseExample > 5")
  case caseExample == 5:
    fmt.Println("caseExample == 5")
  default:
    fmt.Println("default => caseExample < 5")
  }
  1. 循环结构

没有while或do-while循环,只有for循环

  for {
    fmt.Println("loop")
    break
  }
  for i := 1; i < 10; i++ {
    if i%2 == 0 {
      continue
    }
    fmt.Println(i)
  }
  1. 切片

使用make创建切片,使用append进行扩容追加,但append操作后需要赋值给源变量,本质是将扩容后的变量覆盖源变量

  slice := make([]int, 3)
  for i := 0; i < 3; i++ {
    slice[i] = i
  }
  fmt.Println(slice)
  fmt.Println(append(slice, 33))
  fmt.Println(slice)
输出:

[0 1 2]
[0 1 2 33] 
[0 1 2]
  1. map

使用make创建并指定key和value的元素类型,map内元素无序

  m := make(map[string]int)
  m["one"] = 1
  m["two"] = 2
  m["three"] = 3
  fmt.Println(m["two"])
  //判断key是否存在
  v, ok := m["four"]
  if ok {
    fmt.Println("exist four value =", v)
  } else {
    fmt.Println("not exist four")
  }
  //使用delete进行删除某个key-value
  delete(m, "two")
  //使用range进行遍历
  for k, v := range m {
    fmt.Println("key =", k, ", value =", v)
  }
  1. 指针和结构体

go支持如c类似的指针和结构体


type user struct {
  name string
  age  int
}

func main() {
  fmt.Println("hello go")
  a := 1
  add(&a)
  fmt.Println(a)
  //初始化结构体
  u := user{"zhangsan", 13}
  fmt.Println(u)
  changeStruct(&u)
  fmt.Println(u)
}

func add(a *int) {
  *a = *a + 1
}

func changeStruct(u *user) {
  add(&u.age)
}
  1. Printf格式化

可用使用%v对任意类型变量进行打印

使用%+v获得详细结果

使用%#v获得更加详细的结果

type user struct {
  name string
  age  int
}

func main() {
  u := user{"lisi", 14}
  fmt.Printf("%v\n", u)
  fmt.Printf("%+v\n", u)
  fmt.Printf("%#v\n", u)
}
输出:

{lisi 14}
{name:lisi age:14} 
main.user{name:"lisi", age:14}
  1. json序列化

使用json.marshal进行序列化,使用json.unmarshal进行反序列化,但是结构体字段要大写,不然会序列化不出来

type user struct {
  Name string
  Age  int
}

func main() {
  fmt.Println("hello go")
  u := user{"lisi", 14}
  b, err := json.Marshal(u)
  if err != nil {
  }
  fmt.Println(b)
  fmt.Println(string(b))
  json.Unmarshal(b, &u)
  fmt.Println(u)
}
输出:

[123 34 78 97 109 101 34 58 34 108 105 115 105 34 125]
{"Name":"lisi"} 
{lisi 14}

Go变量声明踩坑

众所周知,go声明变量可用使用 varName := value

今天遇到一个坑,相同逻辑的代码(比较简单,没涉及什么高级操作),使用java和python都没问题,但是到了go出现了个数组下标越界问题。后面检查发现了问题所在:变量的重复声明

在同一代码块中,变量不能重复声明如:

a := 1
a := 2

出现no new variables on left side of :=错误警告,但是!!!

当重复声明的变量一个在外面,一个在for循环里面却没有任何问题

  var a int = 1
  for i := 0; i < 2; i++ {
    fmt.Println("f: ", a)
    var a int = 2
    fmt.Println("s: ", (a))
  }
/* 
运行结果:
f:  1
s:  2
f:  1
s:  2
*/

完全正确运行!!!!

我产生错误的原因是偷懒造成的

首先外部有个变量a

在循环内使用自定义函数get获得两个值同时赋给a和b,这里b还没定义,我想同时为a、b赋值但不行单独拿一行定义b,所以===> a, b := get(params),这样就内内部又定义了一个a,后面的对a的操作没有影响外部的a,因此外部a的值一直没变,但循环判断又是用到了外部a,导致错误出现;

下面是个模拟事故出现的程序逻辑:

func main() {
  a := 0
  arr := []int{1, 2, 3}
  c := 0
  for a < 2 {
    a, b := get(c)
    fmt.Println(arr[c], b)
    c = a
    a++
  }
}

func get(p int) (int, int) {
  return p + 1, p + 2
}