Go指南学习笔记(持续更新)

         最近研究室新开始一个基于Hyperledger平台的项目,因此建立了一个Go语言学习小组,打算共同学习一下基础部分。        

        学习资料:Go编程语言官方指南        https://tour.go-zh.org/welcome/1

1. 基础

        1.1 没有分号。                

        1.2 导入包时,更推荐使用分组导入语句的形式。如果一个名字以大写字母开头,那么它就是已导出的。在导入一个包时,只能引用其中已导出的名字,任何未导出的名字在该包外均无法访问。

import (
	"fmt"
	"math"
)

        1.3 函数可以返回任意数量的返回值,且返回值可以被命名。变量名在前,类型在后。当连续两个或多个函数的已命名形参类型相同时,除最后一个类型以外,其他都可以省略。

func swap(x, y string) (string, string) {
	return y, x
}

        1.4 var语句用于声明一个变量列表,可以出现在包或函数级别。变量未指定初始值时,默认为0,false和空字符串。若初始值存在,则可以省略类型,变量会从初始值中自动获取类型。在函数中,可以用简洁赋值语句:=代替var声明。但是常量的声明不可以用:=语句,使用const关键字。

var i, j int = 1, 2
const Pi = 3.14

func main() {
    k := 3	
    var c, python, java = true, false, "no!"
	fmt.Println(i, j, k, c, python, java, Pi)
}

        1.5 在不同类型的项之间赋值时需要显示转换。比如float64转换为uint类型时,必须显示转换。

        1.6 Go只有一种循环结构:for循环。for的条件语句没有小括号,而后必须要有大括号,且部分可省略。if语句类似。

func main() {
	sum := 1
	for ; sum < 1000; {
		sum += sum
	}
	fmt.Println(sum)
}

        1.7 switch语句较灵活,只运行选定的case,默认有break语句。除非以fallthrough语句结束case时,会继续运行下一个case。case无需为常量,取值不必为整数。

switch time.Saturday {
	case today + 0:
		fmt.Println("Today.")
	case today + 1:
		fmt.Println("Tomorrow.")
	default:
		fmt.Println("Too far away.")
}

        1.8 defer语句会将函数推迟到外层函数返回之后执行。推迟调用的函数其参数会立即求值,但其函数调用会被压入一个栈中,直到外层函数返回前都不会被调用。 

        1.9 Println打印的每一项之间都会有空行,Printf需要手动输入。Println以分组形式输出时,注意与单独输出时的区别。

//Go指南if和else部分示例代码 第7页
//输出结果为 9 27>=20 20
fmt.Println(pow(3, 2, 10))
fmt.Println(pow(3, 3, 20))

//输出结果为 27>=20 9 20
fmt.Println(
    pow(3, 2, 10),
    pow(3, 3, 20),
)

        1.10 一个结构体(struct)就是一组字段(field),使用Name:语法可以仅赋值部分字段。结构体输出时自带大括号{},数组输出时自带中括号[]。

//输出结果为 {4 0}
v2 = Vertex{X: 4}  // Y:0 被隐式地赋予

        1.11 数组不能改变大小,因此常用切片。切片通过两个下标来界定,包括第一个元素,但排除最后一个元素。切片下界的默认值为0,上界则是该切片的长度。更改切片的元素会修改其底层数组中对应的元素。

//以下切片等价
a[0:10]
a[:10]
a[0:]
a[:]

        1.12 切片拥有长度和容量。切片的长度就是它所包含的元素个数。切片的容量是从它的第一个元素开始数,到其底层数组元素末尾的个数。切片的零值是nil。

	s := []int{2, 3, 5, 7, 11, 13}	
    printSlice(s)    //len=6 cap=6 [2 3 5 7 11 13]

	// 截取切片使其长度为 0
	s = s[:0]
	printSlice(s)    //len=0 cap=6 []

	// 拓展其长度
	s = s[:4]
	printSlice(s)    //len=4 cap=6 [2 3 5 7]

	// 舍弃前两个值
	s = s[2:]
	printSlice(s)    //len=2 cap=4 [5 7]

        1.13 make函数创建切片,第三个参数为容量,可忽略可指定。

    a := make([]int, 5)
	printSlice("a", a)    //len=5 cap=5 [0 0 0 0 0]

	b := make([]int, 0, 5)
	printSlice("b", b)    //len=0 cap=5 []

	c := b[:2]
	printSlice("c", c)    //len=2 cap=5 [0 0]

	d := c[2:5]
	printSlice("d", d)    //len=3 cap=3 [0 0 0]

        1.14 append函数可以为切片追加新的元素。for循环的range形式可以遍历切片或映射,第一个值为当前元素的下标,第二个值为该下标所对应元素的一份副本,可以按需省略变量。

    var s []int
	printSlice(s)    //len=0 cap=0 []

	// 添加一个空切片
	s = append(s, 0)
	printSlice(s)    //len=1 cap=1 [0]

	// 这个切片会按需增长
	s = append(s, 1)
	printSlice(s)    //len=2 cap=2 [0 1]

	// 可以一次性添加多个元素
	s = append(s, 2, 3, 4)
	printSlice(s)    //len=5 cap=6 [0 1 2 3 4]

3. 并发

        3.1 Go程(goroutine)是由Go运行时管理的轻量级线程。

        3.2 信道是带有类型的管道,可以通过它用信道操作符<-来发送或者接收值。信道初始化时,第二个参数可以作为一个缓冲值。

ch := make(chan int)
ch <- v    //将v发送至信道ch
v := <-ch  //从ch接收值并赋予v

暂时还没弄明白的点:

1.14 当用append一次性添加多个元素时,len和cap的数值问题。(len=5 cap=6?)

        相关回答:https://github.com/golang/tour/issues/398

                          https://www.dazhuanlan.com/2019/11/19/5dd3c31e70fb0/

        好像不是很重要的部分,但是官方回答貌似是每当切片超过其当前容量时,切片的容量通常会增加一倍,预期容量为8?与输出6仍不相符。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值