go数据类型进阶 | 青训营笔记

574 阅读4分钟

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

(内容根据字节跳动青训营课程内容以及自己的理解编写)

近期将日更这几个主题的文章,欢迎关注!

  • 全面理解go协程
  • channel通信
  • Kitex
  • Hertx
  • Gorm
  • go的测试环节

说在前面

基础的数据类型在我上一篇文章里有,传送门

这一篇文章主要讲一些遗漏的数据结构和进阶分析

go语言编译命令

go build

go build 这个是打包用的

打包生成的exe文件会保存在当前目录底下

比如拿hertz_demo项目举例:

image.png

也可以指定打包文件的名字:

go build -o 自定义包名

注意要加.exe后缀

image.png

交叉编译

  1. Go支持跨平台编译
  2. 例如:在mac平台或者Windows平台编译出可以运行在Linux平台的二进制文件
  3. 示例代码:Mac 下编译 Linux 和 Windows平台 64位 可执行程序:
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build

(下面我就不删了,阳哥博客干货很多)

作者:王中阳Go
链接:juejin.cn/post/694279…
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

(前面一个参数是静态编译的,后面一个参数是编译出适合平台的可执行文件)

go run

就是执行文件,和java -jar 一样

go install

go install 分为两步:

  1. 先编译得到一个可执行文件
  2. 将可执行文件拷贝到'GOPATH/bin'

image.png

image.png

iota

iota记住是按照行递增的就行

例子1:

func main() {
   const (
      a1 = iota //0
      a2
      a3
   )

   fmt.Println(a1)
   fmt.Println(a2)
   fmt.Println(a3)
}

image.png

第一个例子大家差不多就能理解iota的运行原理了

不过别急,坑的在下面

例子2:

func main() {
   const (
      a1 = iota //0
      a2        //1
      _         //2
      a4        //3
   )

   fmt.Println(a1)
   fmt.Println(a2)
   fmt.Println(a4)
}

image.png

占位符也算一行

例子3:

这个叫插队情况,是个面试题:

func main() {
   const (
      a1 = iota //0
      a2 = 100  //100
      a3        //100
      a4        //100
   )

   fmt.Println(a1)
   fmt.Println(a2)
   fmt.Println(a3)
   fmt.Println(a4)
}

image.png

例子4:

func main() {
   const (
      a1 = iota //0
      a2 = 100  //100
      a3 = iota //2
      a4        //3
   )

   fmt.Println(a1)
   fmt.Println(a2)
   fmt.Println(a3)
   fmt.Println(a4)
}

image.png

例子5:

func main() {
   const (
      a1, a2 = iota + 1, iota + 2 //1 2
      a3, a4 = iota + 1, iota + 2 //2 3
   )

   fmt.Println(a1)
   fmt.Println(a2)
   fmt.Println(a3)
   fmt.Println(a4)
}

image.png

记住是按照行递增的就行

Go 字符串格式化符号

image.png

切片Slice

切片是对数组一个片段的引用。

切片的本质:切片的本质是一个框,框住了一块连续的内存

判断一个切片是否为空,使用len(s) == 0 判断,不能使用 s==nil 判断

切片的长度和容量

切片的长度很好理解,就是元素的个数。

切片的容量我们重点理解一下:在切片引用的底层数组中从切片的第一个元素到数组最后一个元素的长度就是切片的容量

这句话比较拗口,但是非常正确

例子:

func main() {
   var array [10]int

   slice1 := array[2:7] // 复制数组成切片,从2到6

   fmt.Println(len(slice1)) // 从2到6
   fmt.Println(cap(slice1)) // 从2到最后
}

image.png

slice的自动扩容机制

go 的切片在容量较小的情况下,确实会进行 2 倍扩容,但是随着容量的增长,扩容的增长因子会逐渐降低。 新版本的 growslice 实现中,只有容量小于 256 的时候才会进行 2 倍扩容, 然后随着容量的增长,扩容的因子会逐渐降低(但并不是直接降到 1.25,而是一个相对缓慢的下降)

image.png

具体可以看这篇文章,写的很详细

juejin.cn/post/712249…

切片删除元素

func main() {
   s3 := []int{1, 2, 3}
   s3 = append(s3[:1], s3[2:]...) //第一个不用拆开 原因是一个作为被接受的一方  是把后面的元素追加到第一个
   fmt.Println(s3)
}

image.png

switch

switch概念

补充switch的概念

需要注意的是,不需要在每个分支上加break

普通的:

func main() {
   finger := 2
   switch finger {
   case 1:
      fmt.Println("大拇指")
   case 2:
      fmt.Println("食指")
   case 5:
      fmt.Println("小拇指")
   default:
      fmt.Println("无效")
   }

}

多个值:

switch n {
case 1, 3, 5, 7, 9:
   fmt.Println("奇数")
case 2, 4, 6, 8, 10:
   fmt.Println("偶数")
}

加上判断条件:

age := 29 switch { case age < 18: fmt.Println("好好学习Z") case age > 18 && age < 60: fmt.Println("好好上班") case age > 60: fmt.Println("希望不用继续上班了,哈哈") default: fmt.Println(age) }

判断语句:

switch {
case age < 18:
   fmt.Println("好好学习Z")
case age > 18 && age < 60:
   fmt.Println("好好上班")
case age > 60:
   fmt.Println("希望不用继续上班了,哈哈")
default:
   fmt.Println(age)
}

fallthrough

在一个 switch 块内,每个 case 无需声明 break 来终止 , 如果想顺序执行使用 fallthrough ;在一个switch块内,都必须包含一个 default 语句并且放在最后,即使它什么代码也没有。

age := 29
switch {
case age < 18:
   fmt.Println("好好学习Z")
   fallthrough
case age > 18 && age < 60:
   fmt.Println("好好上班")
   fallthrough
case age > 60:
   fmt.Println("希望不用继续上班了,哈哈")
   fallthrough
case age < 18:
   fmt.Println("好好学习Z")
   fallthrough
default:
   fmt.Println(age)
}

image.png

比如中间第二个case不加的话,fallthrough到第二个分支就会退出switch

总结

虽然go相比java语法简单一些,但是依然会有底层的一些类似机制,比如说自动扩容

资料

深入理解切片

自动扩容