golang 学习文档 文档官网
1. 格式 Go 语言的一些格式不能改变,改变后就会报错。
比如:
函数体、for 循环体等需要使用{}的,左括号不能另起一行。
正确的格式是:
错误的格式是:
var num int = 5 与 num := 5 一样。
在进行var num int之后,不能使用num :=,因为:=也是初始化(并赋值)的意思。
2.break、continue 的高级用法 break 语句可以结束 for、switch 和 select 的代码块。
break 语句还可以在语句后面添加标签 XX(即下面代码中的 BreakTag、BreakTag2),表示退出某个标签对应的代码块。
标签要求必须定义在对应的 for、switch 和 select 的代码块上。
一般来说,switch 中无需写 break,默认存在 break。
1 2 3 4 5 6 7 8 9 10 11 12 13 BreakTag: for i := 0; i < 5; i++ { BreakTag2: for j := 0; j < 4; j++ { fmt.Println(i, j) switch i { case 1: break BreakTag case 3: break BreakTag2 } } }
打印结果:
1 2 3 4 5 6 7 0 0 0 1 0 2 0 3 #缺少 0 4 因为break跳出了BreakTag2循环 1 0 #缺少 1 1 1 2 ..... 因为break跳出了BreakTag循环
continue 与 break 类似。
continue 语句可以结束当前循环,开始下一次的循环迭代过程,仅限在for 循环内 使用。在 continue 语句后添加标签时,表示开始标签对应的循环.
1 2 3 4 5 6 7 8 9 10 11 12 13 ContinueTag: for i := 0; i < 5; i++ { ContinueTag2: for j := 0; j < 4; j++ { fmt.Println(i, j) switch i { case 1: break ContinueTag case 3: break ContinueTag2 } } }
打印结果:
3.自定义函数的参数的数量可变 函数内部处理可变参数的时候,将可变参数当作切片来处理。
举个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 package main import ( "fmt" ) // 定义一个函数,函数的参数为可变参数 ... 参数的数量可变 // args...int 表示可以传入任意多个数量的int类型的数据 传入0个,1个 …… n个 func myFunc(args...int) { // 遍历可变参数: for i:=0;i<len(args);i++{ fmt.Println(args[i]) } } func main() { myFunc() myFunc(1, 2) myFunc(1, 2, 3, 4, 5) }
4. 自定义函数能够改变函数外的值 默认是不会影响原来的值 我们都知道,基本数据类型和数组默认都是值传递的,即进行值拷贝。在函数内修改,不会影响到原来的值。
例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 package main import ( "fmt" ) func test(num int) { num = 30 fmt.Println("test----",num) // 结果为30 } func main() { var num int = 10 test(num) fmt.Println("main----",num) // 结果为10 }
上述例子中函数 test 改变了 num 的值为 30,但是 test 函数内的 num 的内存地址是在 test 函数区域内(这片内存空间我们称为函数 test 的栈帧),main 函数中的 num 的地址是在 main 函数区域内,两个 num 的地址空间不同,所以 main 中的 num 的值不变。
栈一般存放基本数据类型;堆一般存放引用数据类型;代码区存放代码本身。
影响函数外的值 以值传递方式的数据类型,如果希在函数内的变量能修改函数外的变量,可以传入变量的地址&,函数内以指针的方式操作变量。从效果来看类似引用传递。
1 2 3 4 5 6 7 8 9 10 11 12 13 package main import ( "fmt" ) func test(num *int) { *num = 30 // 对该地址对应的变量进行改变数值 } func main() { var num int = 10 fmt.Println(&num) // 结果为num的地址,例如是:0xc0000100b0 test(&num) // 传入的是num的地址 fmt.Println(num) // 结果为30 }
5. 函数与数据类型 5.1 函数也可作为一个数据类型 函数可以赋值给一个变量,则该变量就是一个函数类型的变量了。通过该变量可以对函数调用。
1 2 3 4 5 6 7 8 9 10 11 12 13 package main import ( "fmt" ) func test(num int) { fmt.Println(num) } func main() { a := test fmt.Printf("a的类型是:%T,test函数的类型是:%T\n",a,test) // 输出结果:a的类型是:func(int),test函数的类型是:func(int) a(10) // 等价于 test(10) }
5.2 函数可以作为形参 函数既然是一种数据类型,因此在 Go 中,函数可以作为形参,并且调用。
在 5.1 代码中加入/修改下列代码:
1 2 3 4 5 6 7 8 9 10 11 12 // 加入的 func test02(num1 int, num2 float32, testFunc func(int)) { fmt.Println("test02---") } // 修改的 func main() { a := test // 调用test02函数 test02(10,3.14,test) test02(1,2.1,a) } // 程序运行不报错
5.3 支持自定义数据类型 基本语法为:type [自定义数据类型名] [数据类型]
可以理解为:相当于起了一个别名
例如:
1 2 3 4 5 6 7 8 9 10 11 12 type myInt int var num1 myInt = 30 fmt.Println("num1",num1) var num2 int = 30 // num2 = num1 // 错误的,虽然是别名,但是在go中编译识别的时候还是认为myInt和int不是一种数据类型 num2 = int(num1) // 强转一下就行了。 fmt。Println("num2",num2)
同理,如果我们将 int 换为 func(int,int) int,这时的 myInt 就等价一个函数类型 func(int,int) int
5.4 支持对函数返回值命名 当我们为函数返回值命名时,就不用写 return 了,,但是函数体内必须存在该返回值。
我们传统的写法,return 时必须将返回值一一对应,前后不能调换
例如:
1 2 3 4 5 6 // 传统写法 fun test(num1 int, num2 int)(int,int){ result1 := num1 + num2 result2 := num1 - num2 return result1,result2 }
给返回值命名后,则不用写 return 了,这样顺序就无所谓了
例如:
1 2 3 4 5 6 // 给返回值命名 fun test(num1 int, num2 int)(sum int,sub int){ sum := num1 + num2 sub := num1 - num2 return }
跳过的一些知识点
init 函数
匿名函数
闭包
defer 关键字
10.系统函数
参考链接 1:Golang 中文学习文档 参考链接 2:Golang 标准库文档
10.1 字符串相关函数 10.1.1 字符串长度 统计字符串的长度,按字节进行统计。
使用:len(str)
返回值类型:int
Go 中汉字是 utf-8 编码,所以 1 个汉字是 3 个字节
10.1.2 字符串遍历
1 2 3 4 str := "golang你好" for i, value := range str { fmt.Printf("索引是:%d,具体的值为:%c \n",i,value) }
%c,输出字符
方式 2:字符串转为切片——r:=[]rune(str)
1 2 3 4 5 str := "golang你好" r := []rune(str) for i := 0; i < len(r); i++ { fmt.Println(r[i]) }
上例输出的是 字符对应的字节
改为fmt.Printf("%c \n",r[i]) , 就输出字符了。
10.1.3 字符串与整数互转
1 2 3 4 5 6 7 8 9 10 11 import ( ... "strconv" ) ... // 此处error可以替换为 _ num,error := strconv.Atoi("666") // num为int型 ...
1 2 3 4 5 6 7 8 9 10 11 import ( ... "strconv" ) ... // 此处error可以替换为 _ str := strconv.Itoa(80) // str为string型 ...
10.1.4 查找子串是否在指定的字符串中 1 2 3 4 5 6 import ( "strings" ) isHas := strings.Contains("javaandgolang","go") // isHas为true
10.1.5 统计一个字符串有几个指定的字串 1 2 count := strings.Count("golangandjavaga","ga") // count为2
10.2 内置函数 自带函数,无需引入包就能使用。
package builtin这个不用写,里边都是内置函数。
__END__