go    2024-01-10 17:54:46    17    0    0

Go语言基础语法

标识符与关键字

  go变量、常量、自定义类型、包、函数的命名方式必须遵循以下规则:
1. 首字符可以是任意Unicode字符或下划线。
2. 首字符之外的部分可以是Unicode字符、下划线或数字。
3. 名字的长度无限制。

理论上名字里可以有汉字,甚至可以全是汉字,但实际中不要这么做。

Go语言关键字

  1. break default func interface select case defer go map struct chan else goto package switch const if range type continue for import return fallthrough var

常量

  1. true false iota nil

数据类型

  1. int int8 int16 int32 int64 uint uint8 uint16 uint32 uint64 uintptr float32 float64 complex128 complex64 bool byte rune string error

函数

  1. make len cap new append copy close delete complex real imag panic recover

操作符与表达式

算法术运算符

运算符 描述
+ 相加
- 相减
* 相乘
/ 相除
% 求余
  1. //arithmetic 算术运算
  2. func arithmetic() {
  3. var a f
go    2024-01-10 17:54:46    9    0    0

初识Go语言

Go语言发展历史

阵容豪华的创使人团队

Ken Thompson
- 1966年:加入了贝尔实验室,在参与 Multics (多路信息计算)开发期间,创造出了B语言,并用一个月的时间用B语言开发了全新的操作系统UNICS,后来改名为我们所熟悉的UNIX 操作系统。
- 1971年:和丹尼斯·利奇(Dennis Ritchie)一起共同发明了C语言。
- 1973年:和丹尼斯·利奇(Dennis Ritchie)使用C语言重写了UNIX,并安装于PDP-11的机器之上。
- 1983年:美国计算机协会将图灵奖授予汤普森。
- 2000年:离开贝尔实验室,已退休的汤普森成为了一名飞行员。
- 2006年:加入Google工作。
- 2007年:64岁的高龄,与Rob Pike和Robert Griesemer主导了Go语言的开发。

Rob Pike
- Go语言项目总负责人。
- 贝尔实验室Unix团队成员,参与的项目包括Plan 9,Inferno操作系统和Limbo编程语言。
- UTF-8字符集规范唯二的发明人之一(另一位是Ken Thompson)。
- 《UNIX环境编程》和《程序设计实践》这两本书的作者之一。
- 第22届莫斯科夏季奥运会射箭项目的银牌得主。
- 业余天文学家,设计的珈玛射线望远镜差点被 NASA 用在航天飞机上。
- 他的媳妇Renee French 就是 Go 语言吉祥物的设计人。

Robert Griesemer
- 参与V8 JavaScript引擎的开发。
- 参与Java HotSpot虚拟机的研发。

起源

  2007年,Google的几位大牛正在用C++开发一些比较繁琐但是核心的工作,主要是分布式集群,大牛觉得很闹心。此时C+

go    2024-01-10 17:54:46    20    0    0

结构体

结构体创建、访问与修改

定义结构体

  1. type user struct {
  2. id int
  3. score float32
  4. enrollment time.Time
  5. name, addr string //多个字段类型相同时可以简写到一行里
  6. }

声明和初始化结构体

  1. var u user //声明,会用相应类型的默认值初始化struct里的每一个字段
  2. u = user{} //用相应类型的默认值初始化struct里的每一个字段
  3. u = user{id: 3, name: "zcy"} //赋值初始化
  4. u = user{4, 100.0, time.Now(), "zcy", "beijing"} //赋值初始化,可以不写字段名,但需要跟结构体定义里的字段顺序一致

访问与修改结构体

  1. u.enrollment = time.Now() //给结构体的成员变量赋值
  2. fmt.Printf("id=%d, enrollment=%v, name=%s\n", u.id, u.enrollment, u.name)//访问结构体的成员变量

成员方法

  1. //可以把user理解为hello函数的参数,即hello(u user, man string)
  2. func (u user) hello(man string) {
  3. fmt.Println("hi " + man + ", my name is " + u.name)
  4. }
  5. //函数里不需要访问user的成员,可以传匿名,甚至_也不传
  6. func (_ user) think(man string) {
  7. fmt.Println("hi " + man + ", do you know my name?")
  8. }

为自定义类型添加方法

  1. type UserMap map[int]User //自定义类型
  2. //可以给自定义类型添加任意方法
  3. func (um UserMap) GetUser(id int) User {
  4. return um[id]
  5. }

结构体的可见性:
- go语言关于可见的统一规则:大写字母开头跨package也可以访问;否则只能本pack

go    2024-01-10 17:54:46    14    0    0

函数

函数的基本形式

  1. //函数定义。a,b是形参
  2. func argf(a int, b int) {
  3. a = a + b
  4. }
  5. var x, y int = 3, 6
  6. argf(x, y) //函数调用。x,y是实参
  • 形参是函数内部的局部变量,实参的值会拷贝给形参。
  • 函数定义时的第一个的大括号不能另起一行。
  • 形参可以有0个或多个。
  • 参数类型相同时可以只写一次,比如argf(a,b int)。
  • 在函数内部修改形参的值,实参的值不受影响。
  • 如果想通过函数修改实参,就需要指针类型。
  1. func argf(a, b *int) {
  2. *a = *a + *b
  3. *b = 888
  4. }
  5. var x, y int = 3, 6
  6. argf(&x, &y)

  slice、map、channel都是引用类型,它们作为函数参数时其实跟普通struct没什么区别,都是对struct内部的各个字段做一次拷贝传到函数内部。

  1. package main
  2. import "fmt"
  3. func slice_arg_1(arr []int) { //slice作为参数,实际上是把slice的arrayPointer、len、cap拷贝了一份传进来
  4. arr[0] = 1 //修改底层数据里的首元素
  5. arr = append(arr, 1) //arr的len和cap发生了变化,不会影响实参
  6. }
  7. func main() {
  8. arr := []int{8}
  9. slice_arg_1(arr)
  10. fmt.Println(arr[0]) //1
  11. fmt.Println(len(arr)) //1
  12. }

关于函数返回值
- 可以返回0个或多个参数。
- 可以在func行直接声明要返回的变量。
- return后面的语句不会执行。
- 无返回参数时return可以不写。

  1. func returnf(a, b int) (c int) { //返回变量c已经声明好了
  2. a = a + b
  3. c = a //直接使用c
  4. return //由于函数要求有返回值,即使给c赋过值了,也需
go    2024-01-10 17:54:46    22    0    0

面向接口编程

接口的基本概念

  接口是一组行为规范的集合。

  1. type Transporter interface { //定义接口。通常接口名以er结尾
  2. //接口里面只定义方法,不定义变量
  3. move(src string, dest string) (int, error) //方法名 (参数列表) 返回值列表
  4. whistle(int) int //参数列表和返回值列表里的变量名可以省略
  5. }

  只要结构体拥有接口里声明的所有方法,就称该结构体“实现了接口”。一个struct可以同时实现多个接口。

  1. type Car struct { //定义结构体时无需要显式声明它要实现什么接口
  2. price int
  3. }
  4. func (car Car) move(src string, dest string) (int, error) {
  5. return car.price, nil
  6. }
  7. func (car Car) whistle(n int) int {
  8. return n
  9. }

  接口值有两部分组成, 一个指向该接口的具体类型的指针和另外一个指向该具体类型真实数据的指针。

  1. car := Car{"宝马", 100}
  2. var transporter Transporter
  3. transporter = car

接口的使用

  1. func transport(src, dest string, transporter Transporter) error {
  2. _,err := transporter.move(src, dest)
  3. return err
  4. }
  5. var car Car //Car实现了Transporter接口
  6. var ship Shiper // Shiper实现了Transporter接口
  7. transport("北京", "天津", car)
  8. transport("北京", "天津", ship)

接口的赋值

  1. func (car Car) whistle(n int) int {…}//方法接收者是值
  2. func (ship *Shiper) whistle
go    2024-01-10 17:54:46    15    0    0
go    2024-01-10 17:54:46    5    0    0

Go数据类型

数据类型概览

基础数据类型

数据类型 长度(字节) 默认值 说明 取值范围
bool 1 false 布尔值 true 或 false
byte 1 0 8位无符号整数 0 到 255(和uint8一样)
rune 4 0 Unicode 码点 0 到 0x10FFFF(rune是int32 的别名)
int 4 或 8 0 有符号整数 -2147483648 到 2147483647 或 -9223372036854775808 到 9223372036854775807
uint 4 或 8 0 无符号整数 0 到 4294967295 或 0 到 18446744073709551615
int8 1 0 有符号 8 位整数 -128 到 127
uint8 1 0 无符号 8 位整数 0 到 255
int16 2 0 有符号 16 位整数 -32768 到 32767
uint16 2 0 无符号 16 位整数 0 到 65535
int32 4 0 有符号 32 位整数 -2147483648 到 2147483647(和rune一样)
uint32 4 0 无符号 32 位整数 0 到 4294967295
int64 8 0 有符号 64 位整数 -9223372036854775808 到 9223372036854775807
uint64 8 0 无符号 64 位整数 0 到 18446744073709551615
float32 4 0.0 32 位浮点数 大约 1.18e-38 到 3.4e38
float64 8
go    2024-01-10 17:51:56    30    0    0

报错

Windows平台运行 docker 报如下错误:

  1. start service error, listen tcp 0.0.0.0:8050: bind: An attempt was made to access aions.

原因及解决

根据下列两个方式来排错。

端口占用

  • 查看端口是否被占用
  1. netstat -aon|findstr 2181
  • 如有占用,杀之,没有的话就往下排查
  1. taskkill /pid 8001 -t -f

Hyper-V 保留端口范围

  • 查看 Hyper-V 排除TCP端口范围
  1. netsh interface ipv4 show excludedportrange protocol=tcp
  • 自定义TCP 动态端口范围(执行完后,重启生效)
  1. netsh int ipv4 set dynamic tcp start=49152 num=16384
  2. netsh int ipv6 set dynamic tcp start=49152 num=16384
  • 查看 TCP 动态端口范围
  1. netsh int ipv4 show dynamicport tcp
go    2024-01-10 17:51:56    28    0    0
go    2024-01-10 17:51:56    123    0    0

问题

pkg/mod下的包,在vscode编译器中无法识别并导入

安装一些库的脚本

包下不下来,可以从sg的vps上导包来用

  1. for i in github.com/golang/tools \
  2. github.com/golang/lint \
  3. github.com/golang/mod \
  4. github.com/golang/xerrors \
  5. golang.org/x/lint/golint \
  6. golang.org/x/tools/cmd/guru \
  7. golang.org/x/tools/cmd/gorename \
  8. github.com/golang/net \
  9. github.com/golang/sync \
  10. github.com/golang/crypto \
  11. github.com/golang/debug \
  12. github.com/golang/oauth2 \
  13. github.com/golang/protobuf \
  14. github.com/uudashr/gopkgs/cmd/gopkgs \
  15. github.com/ramya-rao-a/go-outline \
  16. github.com/rogpeppe/godef \
  17. github.com/godoctor/godoctor \
  18. github.com/acroca/go-symbols \
  19. github.com/fatih/gomodifytags \
  20. github.com/haya14busa/goplay/cmd/goplay \
  21. github.com/davidrjenni/reftools/cmd/fillstruct \
  22. github.com/cweill/gotests/... \
  23. github.com/sqs/goreturns \
  24. github.com/josharian/impl \
  25. github.com/go-delve/delve/cmd/dlv
  26. do
  27. echo $i
  28. #go get -u $i && go install $i || exit 1
  29. go install $i
  30. done

vscode 修改配置

1/14