本文主要用于学习Go语言基础语法知识,文中内容来自青训营第一节内容以及菜鸟教程的内容补充。
认识Go语言
Go 语言特色
- 简洁、快速、安全
- 并行、有趣、开源
- 内存管理、数组安全、编译迅速
Go语言的优点
- 高性能、高并发
- 语法简单、学习曲线平缓
- 丰富标准库
- 完善的工具链
- 静态链接
- 快速编译
- 跨平台
- 垃圾回收
Go语言环境安装
安装包下载地址为:https://golang.org/dl/。
推荐看狂神说安装配置环境变量:【狂神说】Go语言零基础学习视频通俗易懂_哔哩哔哩_bilibili
Go语言基础语法
第一个 Go 程序 (Hello,World)
package main import "fmt" func main() { fmt.Println("Hello, World!") }
字符串连接
Go 语言的字符串连接可以通过 + 实现:
package main import "fmt" func main() { fmt.Println("Google" + "Runoob") }
关键字
下面列举了 Go 代码中会使用到的 25 个关键字或保留字:
break | default | func | interface | select |
case | defer | go | map | struct |
chan | else | goto | package | switch |
const | fallthrough | if | range | type |
continue | for | import | return | var |
除了以上介绍的这些关键字,Go 语言还有 36 个预定义标识符:
append | bool | byte | cap | close | complex | complex64 | complex128 | uint16 |
copy | false | float32 | float64 | imag | int | int8 | int16 | uint32 |
int32 | int64 | iota | len | make | new | nil | panic | uint64 |
| println | real | recover | string | true | uint | uint8 | uintptr |
程序一般由关键字、常量、变量、运算符、类型和函数组成。
程序中可能会使用到这些分隔符:括号 (),中括号 [] 和大括号 {}。
程序中可能会使用到这些标点符号:.、,、;、: 和 …。
Go语言变量
变量声明
第一种,指定变量类型,如果没有初始化,则变量默认为零值。
var name string = "qingshan " fmt.Print(name) name = "zhangsan" fmt.Print(name)
第二种,根据值自行判定变量类型。
package main import "fmt" func main() { var d = true fmt.Println(d) }
第三种,如果变量已经使用 var 声明过了,再使用 := 声明变量,就产生编译错误(也是自动类型判断)
var intVal int intVal :=1 // 这时候会产生编译错误,因为 intVal 已经声明,不需要重新声明 intVal := 1 // 此时不会产生编译错误,因为有声明新的变量,因为 := 是一个声明语句
多变量声明
//类型相同多个变量, 非全局变量 var vname1, vname2, vname3 type vname1, vname2, vname3 = v1, v2, v3 var vname1, vname2, vname3 = v1, v2, v3 // 和 python 很像,不需要显示声明类型,自动推断 vname1, vname2, vname3 := v1, v2, v3 // 出现在 := 左侧的变量不应该是已经被声明过的,否则会导致编译错误 // 这种因式分解关键字的写法一般用于声明全局变量 var ( vname1 v_type1 vname2 v_type2 ) 实例 package main import "fmt" var x, y int var ( // 这种因式分解关键字的写法一般用于声明全局变量 a int b bool ) var c, d int = 1, 2 var e, f = 123, "hello" //这种不带声明格式的只能在函数体中出现 //g, h := 123, "hello" func main(){ g, h := 123, "hello" println(x, y, a, b, c, d, e, f, g, h) } 运行结果 0 0 0 false 1 2 123 hello 123 hello
Go 语言常量
常量的定义格式:
const identifier [type] = value
package main import "fmt" func main() { const LENGTH int = 10 const WIDTH int = 5 var area int const a, b, c = 1, false, "str" //多重赋值 area = LENGTH * WIDTH fmt.Printf("面积为 : %d", area) println() println(a, b, c) }
以上实例运行结果为:
面积为 : 50
1 false str
const ( Unknown = 0 Female = 1 Male = 2 )
iota
iota,特殊常量,可以认为是一个可以被编译器修改的常量。
iota 在 const关键字出现时将被重置为 0(const 内部的第一行之前),const 中每新增一行常量声明将使 iota 计数一次(iota 可理解为 const 语句块中的行索引)。
package main import "fmt" func main() { const ( a = iota //0 b //1 c //2 d = "ha" //独立值,iota += 1 e //"ha" iota += 1 f = 100 //iota +=1 g //100 iota +=1 h = iota //7,恢复计数 i //8 ) fmt.Println(a,b,c,d,e,f,g,h,i) } 以上实例运行结果为: 0 1 2 ha ha 100 100 7 8
package main import "fmt" const ( i=1<<iota j=3<<iota k l ) func main() { fmt.Println("i=",i) fmt.Println("j=",j) fmt.Println("k=",k) fmt.Println("l=",l) } 结果: i= 1 j= 6 k= 12 l= 24
Go 语言运算符
与J其他语言大致类似,不做详细描述,具体内容参考菜鸟教程
Go 语言条件语句
if 语句
package main import "fmt" func main() { /* 定义局部变量 */ var a int = 10 /* 使用 if 语句判断布尔表达式 */ if a < 20 { /* 如果条件为 true 则执行以下语句 */ fmt.Printf("a 小于 20\n" ) } fmt.Printf("a 的值为 : %d\n", a) }
if语句后面的布尔表达式不用加括号
switch 语句
switch 语句执行的过程从上至下,直到找到匹配项,匹配项后面也不需要再加 break。
switch 默认情况下 case 最后自带 break 语句,匹配成功后就不会执行其他 case,如果我们需要执行后面的 case,可以使用 fallthrough 。
package main import "fmt" func main() { /* 定义局部变量 */ var grade string = "B" var marks int = 90 switch marks { case 90: grade = "A" case 80: grade = "B" case 50,60,70 : grade = "C" default: grade = "D" } switch { case grade == "A" : fmt.Printf("优秀!\n" ) case grade == "B", grade == "C" : fmt.Printf("良好\n" ) case grade == "D" : fmt.Printf("及格\n" ) case grade == "F": fmt.Printf("不及格\n" ) default: fmt.Printf("差\n" ); } fmt.Printf("你的等级是 %s\n", grade ); } 以上代码执行结果为: 优秀! 你的等级是 A
fallthrough
使用 fallthrough 会强制执行后面的 case 语句,fallthrough 不会判断下一条 case 的表达式结果是否为 true。
package main import "fmt" func main() { switch { case false: fmt.Println("1、case 条件语句为 false") fallthrough case true: fmt.Println("2、case 条件语句为 true") fallthrough case false: fmt.Println("3、case 条件语句为 false") fallthrough case true: fmt.Println("4、case 条件语句为 true") case false: fmt.Println("5、case 条件语句为 false") fallthrough default: fmt.Println("6、默认 case") } } 以上代码执行结果为: 2、case 条件语句为 true 3、case 条件语句为 false 4、case 条件语句为 true
select 语句
select 是 Go 中的一个控制结构,类似于 switch 语句。
select 语句只能用于通道操作,每个 case 必须是一个通道操作,要么是发送要么是接收。
select 语句会监听所有指定的通道上的操作,一旦其中一个通道准备好就会执行相应的代码块。
如果多个通道都准备好,那么 select 语句会随机选择一个通道执行。如果所有通道都没有准备好,那么执行 default 块中的代码。
package main import ( "fmt" "time" ) func main() { c1 := make(chan string) c2 := make(chan string) go func() { time.Sleep(1 * time.Second) c1 <- "one" }() go func() { time.Sleep(2 * time.Second) c2 <- "two" }() for i := 0; i < 2; i++ { select { case msg1 := <-c1: fmt.Println("received", msg1) case msg2 := <-c2: fmt.Println("received", msg2) } } } 以上代码执行结果为: received one received two
以上实例中,我们创建了两个通道 c1 和 c2。
select 语句等待两个通道的数据。如果接收到 c1 的数据,就会打印 "received one";如果接收到 c2 的数据,就会打印 "received two"。
以下实例中,我们定义了两个通道,并启动了两个协程(Goroutine)从这两个通道中获取数据。在 main 函数中,我们使用 select 语句在这两个通道中进行非阻塞的选择,如果两个通道都没有可用的数据,就执行 default 子句中的语句。
以下实例执行后会不断地从两个通道中获取到的数据,当两个通道都没有可用的数据时,会输出 "no message received"。
package main import "fmt" func main() { // 定义两个通道 ch1 := make(chan string) ch2 := make(chan string) // 启动两个 goroutine,分别从两个通道中获取数据 go func() { for { ch1 <- "from 1" } }() go func() { for { ch2 <- "from 2" } }() // 使用 select 语句非阻塞地从两个通道中获取数据 for { select { case msg1 := <-ch1: fmt.Println(msg1) case msg2 := <-ch2: fmt.Println(msg2) default: // 如果两个通道都没有可用的数据,则执行这里的语句 fmt.Println("no message received") } } }
注意:Go 没有三目运算符,所以不支持 ?: 形式的条件判断。
Go 语言循环语句
Go语言只有for循环语句,在循环过程中支持break、continue、goto语句,用法与其他语言类似
Go 语言函数
函数定义
/* 函数返回两个数的最大值 */ func max(num1, num2 int) int { /* 声明局部变量 */ var result int if (num1 > num2) { result = num1 } else { result = num2 } return result }
注意:函数传参类型和返回值类型后置
函数返回多个值
package main import "fmt" func swap(x, y string) (string, string) { return y, x } func main() { a, b := swap("Google", "Runoob") fmt.Println(a, b) }
以上实例执行结果为:
Runoob Google
Go 语言函数作为实参
Go 语言可以很灵活的创建函数,并作为另外一个函数的实参。以下实例中我们在定义的函数中初始化一个变量,该函数仅仅是为了使用内置函数 math.sqrt(),实例为:
package main import ( "fmt" "math" ) func main(){ /* 声明函数变量 */ getSquareRoot := func(x float64) float64 { return math.Sqrt(x) } /* 使用函数 */ fmt.Println(getSquareRoot(9)) } 结果: 3
Go 语言函数闭包
Go 语言支持匿名函数,可作为闭包。匿名函数是一个"内联"语句或表达式。匿名函数的优越性在于可以直接使用函数内的变量,不必申明。
以下实例中,我们创建了函数 getSequence() ,返回另外一个函数。该函数的目的是在闭包中递增 i 变量,代码如下:
package main import "fmt" func getSequence() func() int { i:=0 return func() int { i+=1 return i } } func main(){ /* nextNumber 为一个函数,函数 i 为 0 */ nextNumber := getSequence() /* 调用 nextNumber 函数,i 变量自增 1 并返回 */ fmt.Println(nextNumber()) fmt.Println(nextNumber()) fmt.Println(nextNumber()) /* 创建新的函数 nextNumber1,并查看结果 */ nextNumber1 := getSequence() fmt.Println(nextNumber1()) fmt.Println(nextNumber1()) } 结果为: 1 2 3 1 2
Go 语言函数方法
Go 语言中同时有函数和方法。一个方法就是一个包含了接受者的函数,接受者可以是命名类型或者结构体类型的一个值或者是一个指针。所有给定类型的方法属于该类型的方法集。
package main import ( "fmt" ) /* 定义结构体 */ type Circle struct { radius float64 } func main() { var c1 Circle c1.radius = 10.00 fmt.Println("圆的面积 = ", c1.getArea()) } //该 method 属于 Circle 类型对象中的方法 func (c Circle) getArea() float64 { //c.radius 即为 Circle 类型对象中的属性 return 3.14 * c.radius * c.radius } 结果: 圆的面积 = 314
Go 语言变量作用域
作用域为已声明标识符所表示的常量、类型、变量、函数或包在源代码中的作用范围。
Go 语言中变量可以在三个地方声明:
- 函数内定义的变量称为局部变量
- 函数外定义的变量称为全局变量
- 函数定义中的变量称为形式参数
Go 语言数组
声明数组
var balance [10] float32
初始化数组
var balance = [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0} balance := [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0} 如果数组长度不确定,可以使用 ... 代替数组的长度,编译器会根据元素个数自行推断数组的长度 var balance = [...]float32{1000.0, 2.0, 3.4, 7.0, 50.0} 或 balance := [...]float32{1000.0, 2.0, 3.4, 7.0, 50.0} 如果设置了数组的长度,我们还可以通过指定下标来初始化元素: balance := [5]float32{1:2.0,3:7.0}
访问数组元素
package main import "fmt" func main() { var n [10]int /* n 是一个长度为 10 的数组 */ var i,j int /* 为数组 n 初始化元素 */ for i = 0; i < 10; i++ { n[i] = i + 100 /* 设置元素为 i + 100 */ } /* 输出每个数组元素的值 */ for j = 0; j < 10; j++ { fmt.Printf("Element[%d] = %d\n", j, n[j] ) } } 以上实例执行结果如下: Element[0] = 100 Element[1] = 101 Element[2] = 102 Element[3] = 103 Element[4] = 104 Element[5] = 105 Element[6] = 106 Element[7] = 107 Element[8] = 108 Element[9] = 109
package main import "fmt" func main() { var i,j,k int // 声明数组的同时快速初始化数组 balance := [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0} /* 输出数组元素 */ ... for i = 0; i < 5; i++ { fmt.Printf("balance[%d] = %f\n", i, balance[i] ) } balance2 := [...]float32{1000.0, 2.0, 3.4, 7.0, 50.0} /* 输出每个数组元素的值 */ for j = 0; j < 5; j++ { fmt.Printf("balance2[%d] = %f\n", j, balance2[j] ) } // 将索引为 1 和 3 的元素初始化 balance3 := [5]float32{1:2.0,3:7.0} for k = 0; k < 5; k++ { fmt.Printf("balance3[%d] = %f\n", k, balance3[k] ) } } 以上实例执行结果如下: balance[0] = 1000.000000 balance[1] = 2.000000 balance[2] = 3.400000 balance[3] = 7.000000 balance[4] = 50.000000 balance2[0] = 1000.000000 balance2[1] = 2.000000 balance2[2] = 3.400000 balance2[3] = 7.000000 balance2[4] = 50.000000 balance3[0] = 0.000000 balance3[1] = 2.000000 balance3[2] = 0.000000 balance3[3] = 7.000000 balance3[4] = 0.000000
二维数组
a := [3][4]int{ {0, 1, 2, 3} , /* 第一行索引为 0 */ {4, 5, 6, 7} , /* 第二行索引为 1 */ {8, 9, 10, 11}, /* 第三行索引为 2 */ } 注意:以上代码中倒数第二行的 } 必须要有逗号,因为最后一行的 } 不能单独一行,也可以写成这样: a := [3][4]int{ {0, 1, 2, 3} , /* 第一行索引为 0 */ {4, 5, 6, 7} , /* 第二行索引为 1 */ {8, 9, 10, 11}} /* 第三行索引为 2 */
package main import "fmt" func main() { // 创建空的二维数组 animals := [][]string{} // 创建三一维数组,各数组长度不同 row1 := []string{"fish", "shark", "eel"} row2 := []string{"bird"} row3 := []string{"lizard", "salamander"} // 使用 append() 函数将一维数组添加到二维数组中 animals = append(animals, row1) animals = append(animals, row2) animals = append(animals, row3) // 循环输出 for i := range animals { fmt.Printf("Row: %v\n", i) fmt.Println(animals[i]) } } 以上实例运行输出结果为: Row: 0 [fish shark eel] Row: 1 [bird] Row: 2 [lizard salamander]
Go 语言指针
如何使用指针
指针使用流程:
- 定义指针变量。
- 为指针变量赋值。
- 访问指针变量中指向地址的值。
在指针类型前面加上 * 号(前缀)来获取指针所指向的内容。
package main import "fmt" func main() { var a int= 20 /* 声明实际变量 */ var ip *int /* 声明指针变量 */ ip = &a /* 指针变量的存储地址 */ fmt.Printf("a 变量的地址是: %x\n", &a ) /* 指针变量的存储地址 */ fmt.Printf("ip 变量储存的指针地址: %x\n", ip ) /* 使用指针访问值 */ fmt.Printf("*ip 变量的值: %d\n", *ip ) } 以上实例执行输出结果为: a 变量的地址是: 20818a220 ip 变量储存的指针地址: 20818a220 *ip 变量的值: 20
指针数组
package main import "fmt" const MAX int = 3 func main() { a := []int{10,100,200} var i int var ptr [MAX]*int; for i = 0; i < MAX; i++ { ptr[i] = &a[i] /* 整数地址赋值给指针数组 */ } for i = 0; i < MAX; i++ { fmt.Printf("a[%d] = %d\n", i,*ptr[i] ) } } 以上代码执行输出结果为: a[0] = 10 a[1] = 100 a[2] = 200
指针作为函数参数
package main import "fmt" func main() { /* 定义局部变量 */ var a int = 100 var b int= 200 fmt.Printf("交换前 a 的值 : %d\n", a ) fmt.Printf("交换前 b 的值 : %d\n", b ) /* 调用函数用于交换值 * &a 指向 a 变量的地址 * &b 指向 b 变量的地址 */ swap(&a, &b); fmt.Printf("交换后 a 的值 : %d\n", a ) fmt.Printf("交换后 b 的值 : %d\n", b ) } func swap(x *int, y *int) { var temp int temp = *x /* 保存 x 地址的值 */ *x = *y /* 将 y 赋值给 x */ *y = temp /* 将 temp 赋值给 y */ } 以上实例允许输出结果为: 交换前 a 的值 : 100 交换前 b 的值 : 200 交换后 a 的值 : 200 交换后 b 的值 : 100
Go 语言结构体
定义结构体
package main import "fmt" type Books struct { title string author string subject string book_id int } func main() { // 创建一个新的结构体 fmt.Println(Books{"Go 语言", "www.runoob.com", "Go 语言教程", 6495407}) // 也可以使用 key => value 格式 fmt.Println(Books{title: "Go 语言", author: "www.runoob.com", subject: "Go 语言教程", book_id: 6495407}) // 忽略的字段为 0 或 空 fmt.Println(Books{title: "Go 语言", author: "www.runoob.com"}) } 输出结果为: {Go 语言 www.runoob.com Go 语言教程 6495407} {Go 语言 www.runoob.com Go 语言教程 6495407} {Go 语言 www.runoob.com 0}
结构体作为函数参数
package main import "fmt" type Books struct { title string author string subject string book_id int } func main() { var Book1 Books /* 声明 Book1 为 Books 类型 */ var Book2 Books /* 声明 Book2 为 Books 类型 */ /* book 1 描述 */ Book1.title = "Go 语言" Book1.author = "www.runoob.com" Book1.subject = "Go 语言教程" Book1.book_id = 6495407 /* book 2 描述 */ Book2.title = "Python 教程" Book2.author = "www.runoob.com" Book2.subject = "Python 语言教程" Book2.book_id = 6495700 /* 打印 Book1 信息 */ printBook(Book1) /* 打印 Book2 信息 */ printBook(Book2) } func printBook( book Books ) { fmt.Printf( "Book title : %s\n", book.title) fmt.Printf( "Book author : %s\n", book.author) fmt.Printf( "Book subject : %s\n", book.subject) fmt.Printf( "Book book_id : %d\n", book.book_id) } 以上实例执行运行结果为: Book title : Go 语言 Book author : www.runoob.com Book subject : Go 语言教程 Book book_id : 6495407 Book title : Python 教程 Book author : www.runoob.com Book subject : Python 语言教程 Book book_id : 6495700
结构体指针
package main import "fmt" type Books struct { title string author string subject string book_id int } func main() { var Book1 Books /* 声明 Book1 为 Books 类型 */ var Book2 Books /* 声明 Book2 为 Books 类型 */ /* book 1 描述 */ Book1.title = "Go 语言" Book1.author = "www.runoob.com" Book1.subject = "Go 语言教程" Book1.book_id = 6495407 /* book 2 描述 */ Book2.title = "Python 教程" Book2.author = "www.runoob.com" Book2.subject = "Python 语言教程" Book2.book_id = 6495700 /* 打印 Book1 信息 */ printBook(&Book1) /* 打印 Book2 信息 */ printBook(&Book2) } func printBook( book *Books ) { fmt.Printf( "Book title : %s\n", book.title) fmt.Printf( "Book author : %s\n", book.author) fmt.Printf( "Book subject : %s\n", book.subject) fmt.Printf( "Book book_id : %d\n", book.book_id) } 以上实例执行运行结果为: Book title : Go 语言 Book author : www.runoob.com Book subject : Go 语言教程 Book book_id : 6495407 Book title : Python 教程 Book author : www.runoob.com Book subject : Python 语言教程 Book book_id : 6495700
Go 语言切片(Slice)
len() 和 cap() 函数
切片是可索引的,并且可以由 len() 方法获取长度。
切片提供了计算容量的方法 cap() 可以测量切片最长可以达到多少。
以下为具体实例:
package main import "fmt" func main() { var numbers = make([]int,3,5) printSlice(numbers) } func printSlice(x []int){ fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x) } 以上实例运行输出结果为: len=3 cap=5 slice=[0 0 0]
切片截取
package main import "fmt" func main() { /* 创建切片 */ numbers := []int{0,1,2,3,4,5,6,7,8} printSlice(numbers) /* 打印原始切片 */ fmt.Println("numbers ==", numbers) /* 打印子切片从索引1(包含) 到索引4(不包含)*/ fmt.Println("numbers[1:4] ==", numbers[1:4]) /* 默认下限为 0*/ fmt.Println("numbers[:3] ==", numbers[:3]) /* 默认上限为 len(s)*/ fmt.Println("numbers[4:] ==", numbers[4:]) numbers1 := make([]int,0,5) printSlice(numbers1) /* 打印子切片从索引 0(包含) 到索引 2(不包含) */ number2 := numbers[:2] printSlice(number2) /* 打印子切片从索引 2(包含) 到索引 5(不包含) */ number3 := numbers[2:5] printSlice(number3) } func printSlice(x []int){ fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x) } 执行以上代码输出结果为: len=9 cap=9 slice=[0 1 2 3 4 5 6 7 8] numbers == [0 1 2 3 4 5 6 7 8] numbers[1:4] == [1 2 3] numbers[:3] == [0 1 2] numbers[4:] == [4 5 6 7 8] len=0 cap=5 slice=[] len=2 cap=9 slice=[0 1] len=3 cap=7 slice=[2 3 4]
append() 和 copy() 函数
package main import "fmt" func main() { var numbers []int printSlice(numbers) /* 允许追加空切片 */ numbers = append(numbers, 0) printSlice(numbers) /* 向切片添加一个元素 */ numbers = append(numbers, 1) printSlice(numbers) /* 同时添加多个元素 */ numbers = append(numbers, 2,3,4) printSlice(numbers) /* 创建切片 numbers1 是之前切片的两倍容量*/ numbers1 := make([]int, len(numbers), (cap(numbers))*2) /* 拷贝 numbers 的内容到 numbers1 */ copy(numbers1,numbers) printSlice(numbers1) } func printSlice(x []int){ fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x) } 以上代码执行输出结果为: len=0 cap=0 slice=[] len=1 cap=1 slice=[0] len=2 cap=2 slice=[0 1] len=5 cap=6 slice=[0 1 2 3 4] len=5 cap=12 slice=[0 1 2 3 4]
Go 语言范围(Range)
Go 语言中 range 关键字用于 for 循环中迭代数组(array)、切片(slice)、通道(channel)或集合(map)的元素。在数组和切片中它返回元素的索引和索引对应的值,在集合中返回 key-value 对。
package main import "fmt" func main() { map1 := make(map[int]float32) map1[1] = 1.0 map1[2] = 2.0 map1[3] = 3.0 map1[4] = 4.0 // 读取 key 和 value for key, value := range map1 { fmt.Printf("key is: %d - value is: %f\n", key, value) } // 读取 key for key := range map1 { fmt.Printf("key is: %d\n", key) } // 读取 value for _, value := range map1 { fmt.Printf("value is: %f\n", value) } } 以上实例运行输出结果为: key is: 4 - value is: 4.000000 key is: 1 - value is: 1.000000 key is: 2 - value is: 2.000000 key is: 3 - value is: 3.000000 key is: 1 key is: 2 key is: 3 key is: 4 value is: 1.000000 value is: 2.000000 value is: 3.000000 value is: 4.000000
Go 语言Map(集合)
定义 Map
// 创建一个空的 Map m := make(map[string]int) // 创建一个初始容量为 10 的 Map m := make(map[string]int, 10)
实例
package main import "fmt" func main() { var siteMap map[string]string /*创建集合 */ siteMap = make(map[string]string) /* map 插入 key - value 对,各个国家对应的首都 */ siteMap [ "Google" ] = "谷歌" siteMap [ "Runoob" ] = "菜鸟教程" siteMap [ "Baidu" ] = "百度" siteMap [ "Wiki" ] = "维基百科" /*使用键输出地图值 */ for site := range siteMap { fmt.Println(site, "首都是", siteMap [site]) } /*查看元素在集合中是否存在 */ name, ok := siteMap [ "Facebook" ] /*如果确定是真实的,则存在,否则不存在 */ /*fmt.Println(capital) */ /*fmt.Println(ok) */ if (ok) { fmt.Println("Facebook 的 站点是", name) } else { fmt.Println("Facebook 站点不存在") } } 以上实例运行结果为: Wiki 首都是 维基百科 Google 首都是 谷歌 Runoob 首都是 菜鸟教程 Baidu 首都是 百度 Facebook 站点不存在
delete() 函数
package main import "fmt" func main() { /* 创建map */ countryCapitalMap := map[string]string{"France": "Paris", "Italy": "Rome", "Japan": "Tokyo", "India": "New delhi"} fmt.Println("原始地图") /* 打印地图 */ for country := range countryCapitalMap { fmt.Println(country, "首都是", countryCapitalMap [ country ]) } /*删除元素*/ delete(countryCapitalMap, "France") fmt.Println("法国条目被删除") fmt.Println("删除元素后地图") /*打印地图*/ for country := range countryCapitalMap { fmt.Println(country, "首都是", countryCapitalMap [ country ]) } } 以上实例运行结果为: 原始地图 India 首都是 New delhi France 首都是 Paris Italy 首都是 Rome Japan 首都是 Tokyo 法国条目被删除 删除元素后地图 Italy 首都是 Rome Japan 首都是 Tokyo India 首都是 New delhi
Go 语言类型转换
数值类型转换
var a int = 10 var b float64 = float64(a)
字符串类型转换
package main import ( "fmt" "strconv" ) func main() { str := "123" num, err := strconv.Atoi(str) if err != nil { fmt.Println("转换错误:", err) } else { fmt.Printf("字符串 '%s' 转换为整数为:%d\n", str, num) } } 以上实例执行输出结果为: 字符串 '123' 转换为整数为:123
注意,strconv.Atoi 函数返回两个值,第一个是转换后的整型值,第二个是可能发生的错误,我们可以使用空白标识符 _ 来忽略这个错误
package main import ( "fmt" "strconv" ) func main() { num := 123 str := strconv.Itoa(num) fmt.Printf("整数 %d 转换为字符串为:'%s'\n", num, str) } 以上实例执行输出结果为: 整数 123 转换为字符串为:'123'
package main import ( "fmt" "strconv" ) func main() { str := "3.14" num, err := strconv.ParseFloat(str, 64) if err != nil { fmt.Println("转换错误:", err) } else { fmt.Printf("字符串 '%s' 转为浮点型为:%f\n", str, num) } } 以上实例执行输出结果为: 字符串 '3.14' 转为浮点型为:3.140000
package main import ( "fmt" "strconv" ) func main() { num := 3.14 str := strconv.FormatFloat(num, 'f', 2, 64) fmt.Printf("浮点数 %f 转为字符串为:'%s'\n", num, str) } 以上实例执行输出结果为: 浮点数 3.140000 转为字符串为:'3.14'
接口类型转换
接口类型转换有两种情况:类型断言和类型转换。
package main import "fmt" func main() { var i interface{} = "Hello, World" str, ok := i.(string) if ok { fmt.Printf("'%s' is a string\n", str) } else { fmt.Println("conversion failed") } }
以上实例中,我们定义了一个接口类型变量 i,并将它赋值为字符串 "Hello, World"。然后,我们使用类型断言将 i 转换为字符串类型,并将转换后的值赋值给变量 str。最后,我们使用 ok 变量检查类型转换是否成功,如果成功,我们打印转换后的字符串;否则,我们打印转换失败的消息。
package main import "fmt" type Writer interface { Write([]byte) (int, error) } type StringWriter struct { str string } func (sw *StringWriter) Write(data []byte) (int, error) { sw.str += string(data) return len(data), nil } func main() { var w Writer = &StringWriter{} sw := w.(*StringWriter) sw.str = "Hello, World" fmt.Println(sw.str) }
以上实例中,我们定义了一个 Writer 接口和一个实现了该接口的结构体 StringWriter。然后,我们将 StringWriter 类型的指针赋值给 Writer 接口类型的变量 w。接着,我们使用类型转换将 w 转换为 StringWriter 类型,并将转换后的值赋值给变量 sw。最后,我们使用 sw 访问 StringWriter 结构体中的字段 str,并打印出它的值。
Go 时间处理
package main import ( "fmt" "time" ) func main() { now := time.Now() fmt.Println(now) 2023-05-15 12:53:46.020435014 +0000 UTC m=+0.000048703 t1 := time.Date(2023, 05, 15, 1, 25, 36, 0, time.UTC) t2 := time.Date(2023, 05, 15, 2, 30, 36, 0, time.UTC) fmt.Println(t1) //2023-05-15 01:25:36 +0000 UTC fmt.Println(t1.Year(), t1.Month(), t1.Day(), t1.Hour(), t1.Minute()) //2023 May 15 1 25 fmt.Println(t1.Format("2006-01-02 15:04:05")) //2023-05-15 01:25:36 diff := t2.Sub(t1) fmt.Println(diff) //1h5m0s fmt.Println(diff.Minutes(), diff.Seconds()) // 65 3900 t3, err := time.Parse("2006-01-02 15:04:05", "2023-05-15 1:25:36") if err != nil { fmt.Println(err) } fmt.Println(t3 == t1) //true fmt.Println(now.Unix()) // 1684155226 }
Go 语言接口
package main import ( "fmt" ) type Phone interface { call() } type NokiaPhone struct { } func (nokiaPhone NokiaPhone) call() { fmt.Println("I am Nokia, I can call you!") } type IPhone struct { } func (iPhone IPhone) call() { fmt.Println("I am iPhone, I can call you!") } func main() { var phone Phone phone = new(NokiaPhone) phone.call() phone = new(IPhone) phone.call() } I am Nokia, I can call you! I am iPhone, I can call you!
package main import "fmt" type Shape interface { area() float64 } type Rectangle struct { width float64 height float64 } func (r Rectangle) area() float64 { return r.width * r.height } type Circle struct { radius float64 } func (c Circle) area() float64 { return 3.14 * c.radius * c.radius } func main() { var s Shape s = Rectangle{width: 10, height: 5} fmt.Printf("矩形面积: %f\n", s.area()) s = Circle{radius: 3} fmt.Printf("圆形面积: %f\n", s.area()) } 矩形面积: 50.000000 圆形面积: 28.260000
需要注意的是,接口类型变量可以存储任何实现了该接口的类型的值。在示例中,我们将 Rectangle 和 Circle 类型的实例都赋值给了 Shape 类型的变量 s,并通过 area() 方法调用它们的面积计算方法。
目录