linux cpu占用率如何看
291
2022-09-07
Go语言学习笔记(二)
目录
Go基础
Hello World例子说明
{的问题
iota
Go语言中=和:=的区别
闭包
多维数组
指针
结构体
Map(集合)
make函数
接口
并发
总结
Go基础
因为我自己是有其它编程语言的基础,为了更加快速学习,我这里记录我自己觉得稍微值得关注的知识点。
Hello World例子说明
Hello World例子:
package main import "fmt" func main() { fmt.Println("Hello World") } |
“package main”定义了包名,必须在第一行指明这个文件属于哪个包,“package main”表示一个可独立执行的程序,而且每个Go应用程序都包含一个名为“main”的包,这类似程序的入口。
{的问题
Go语言的“{”是不能单独一行的,不然会报以下错误:
# command-line-arguments .\Demo1.go:5:6: missing function body .\Demo1.go:6:1: syntax error: unexpected semicolon or newline before { |
这个确实和Java语言这些不一样,当然只要我们用的是集成开发工具,都会自动辅助生成代码,一般也不会范这些错误。
像GoLand软件,我们可以直接用格式化代码快捷键“Ctrl+Alt+L”,就会帮我们直接格式化代码。
iota
iota,是go语言里的常量计数器,只能在常量的表达式里使用。
iota可以理解为const语句块中的行索引。
使用方式如下:
const( a = iota b = iota c = iota d = iota ) fmt.Println(a,b,c,d) |
执行结果为:
0 1 2 3 |
当然,大家也可以采用简化形式:
const( a1 = iota b1 c1 d1 ) fmt.Println(a1,b1,c1,d1) |
执行结果为:
0 1 2 3 |
如果常量里有其它数据类型,会是什么情况?
const( a2 = iota b2 c2 d2 e2 = "e2" f2 g2 ) fmt.Println(a2,b2,c2,d2,e2,f2,g2) |
其中e2为字符串类型,并赋值,那我们执行看看是什么现象。
0 1 2 3 e2 e2 e2 |
可以看到,f2和g2并不会继续自增。
那如果是下面这样呢?
const( a3 = iota b3 c3 d3 e3 = "e3" f3 = iota g3 ) fmt.Println(a3,b3,c3,d3,e3,f3,g3) |
我们把f3重新设置为iota。
执行结果如下:
0 1 2 3 e3 5 6 |
可以看到,f3和g3会重新自增,而且和他们当前行的索引是一致。
Go语言中=和:=的区别
:=是通过系统自动推断类型,不需要var关键字,可以简化我们代码,当然可能会影响我们代码的阅读性,这个就看大家的取舍了。
示例:
package main import "fmt" func main() { var res1 int = 0 res1 = fuzhi() fmt.Println(res1) fmt.Println("----------") res2 := fuzhi() fmt.Println(res2) } func fuzhi() int { var a = 100 return a } |
结果:
闭包
Go语言也是支持匿名函数,即闭包。跟其他语言的闭包用法也是大同小异。
示例:
package main import "fmt" func main() { clo := closure() fmt.Println(clo()) fmt.Println(clo()) fmt.Println(clo()) } /** 定义一个闭包示例函数 创建closure()函数,内嵌一个返回函数(匿名) 该匿名函数实现 i 自增 */ func closure() func() int { i := 0 return func() int { i += 1 return i } } |
结果:
使用闭包,最大一个好处就是可以直接使用闭包函数内的变量,不需要重新申明。
多维数组
var variable_name [SIZE1][SIZE2]...[SIZEN] variable_type |
示例:
var thrDim1 [3][2] int var thrDim2 [3][4][3] int |
在我们实际使用中,用得最多的是二维和三维数组。
下面我们写几个代码试试,看看效果。
package main import "fmt" func main() { // 第一种使用示例 var thrDim1 = [3][4]int{ {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}} fmt.Println(thrDim1[0][0]) // 第二种使用示例 thrDim2 := [3][4]int{ {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}} fmt.Println(thrDim2[1][1]) // 第三种使用示例 thrDim3 := [][]int{} r1 := []int{1,2,3} r2 := []int{4,5,6} // 使用append()函数将一维数组添加到多维数组 thrDim3 = append(thrDim3,r1) thrDim3 = append(thrDim3,r2) fmt.Println(thrDim3[0][1]) } |
运行结果:
指针
指针这概念,自己在学C系的编程语言的时候接触比较多,没想到Go语言这里也有。
什么是指针?一个指针变量指向了一个值的内存地址。Go语言的取地址符是&,放到一个变量前使用就会返回相应变量的内存地址。
var var_name *var-type |
说明:
var-type 为指针类型,var_name 为指针变量名,* 号用于指定变量是作为一个指针。
示例:
package main import "fmt" func main() { var a int = 1 fmt.Println(&a) } |
运行结果:
结构体
结构体可以为不同项定义不同的数据类型,类似Java的实体对象类一样。这和数组是有一点不同,数组一般都是存储相同类型的数据。
结构体格式如下:
type struct_variable_type struct { member definition member definition ... member definition }
结构体定义需要使用type和struct语句。
示例:
package mainimport "fmt"type People struct { name string age int}func main() { // 直接赋值 fmt.Println(People{"zhangsan", 10}) // key-value方式赋值 fmt.Println(People{name: "lisi", age: 15}) // 可以按需赋值 fmt.Println(People{name: "zhaowu"}) fmt.Println(People{age: 20})}
运行结果:
从上面效果来看,go语言的结构体用法和Java的对象概念很接近,其余用法也类似Java的,这里就不详细讲解了。
Map(集合)
var map_variable map[key_data_type]value_data_type
我们先写个demo看看:
package mainimport "fmt"func main() { var people map[string]string people ["张三"] = "zhangsan" people ["李四"] = "lisi" fmt.Println(people["李四"])}
运行后,发现报错了:
panic: assignment to entry in nil mapgoroutine 1 [running]:main.main() E:/ispeasant/github/bwzydy4learn/Go/GoDemo/myMathPackage/demo7.go:8 +0x32Process finished with the exit code 2
修正后:
运行效果如下:
lisiProcess finished with the exit code 0
就这个相对比较特殊,其余api练习,这里就不一一展示了。
make函数
Go语言的make函数,还是有点新奇的,你可以理解为Java语言中的new。Go语言中的make函数,是内建函数,主要用来为slice、map或chan类型分配内存和初始化对象,也只能用于这三种类型。
接口
Go语言也有类似Java语言的接口,但Go语言更强调的是数据类型即接口,把类似的方法放在一起,当我们需要实现这些方法的时候,只需要实现这个接口即可。
示例:
package mainimport "fmt"// 定义接口type PeopleDemo interface { speak()}// 定义结构体type ZhangSan struct {}// 实现接口方法func (zhangsan ZhangSan) speak() { fmt.Println("我是张三")}func main() { var people PeopleDemo = new(ZhangSan) people.speak()}
运行结果:
但在我学习过程中,让我有点好奇的是,为什么必须定义结构体,而且实现接口的时候,为什么需要传入结构体?先把问题放在这里,后续在学习过程中,看能否找到答案。
并发
让我决定学Go语言,主要是大家都说Go语言的并发能力很厉害,而且使用很方便,所以自己就开始接触Go语言。
Go语言使用并发,很简单,就是用go这个关键字来启动,我们先看看示例:
package mainimport ( "fmt" "time")func speak(info string) { // 为了方便测试,让代码循环执行多次,并每次中间有等待时间 for i := 0; i < 10; i++ { time.Sleep(1000 * time.Millisecond) fmt.Println(info) }}func main() { speak("A") speak("B")}
运行效果:
AAAAAAAAAABBBBBBBBBBProcess finished with the exit code 0
因此,可以看出,speak()这个方法是串行执行,并不是并行执行,那我们把第一个speak()方法用并发方式来执行看看。
代码:
package mainimport ( "fmt" "time")func speak(info string) { // 为了方便测试,让代码循环执行多次,并每次中间有等待时间 for i := 0; i < 10; i++ { time.Sleep(1000 * time.Millisecond) fmt.Println(info) }}func main() { go speak("A") speak("B")}
运行效果:
BAABABBAABBAABBABAABProcess finished with the exit code 0
因此,我们可以看出,并不是先执行完第一个方法后再执行第二个,而是没有固定先后顺序,证明我们的并发方式是有效的。
总结
到此为止,我们基本把Go语言的基础内容都过了一遍,当然只掌握这些,是不够用于项目中,后续我们还是需要加深的去研究。后续有新的内容,再与大家分享。
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~