Hello Go
package main import "fmt" func main() { fmt.Println("hello go") }
变量的声明
局部变量
// 方法一:声明一个变量 默认值为0 var a int // 方法二:声明并初始化一个变量 var b int = 10 // 方法三:声明一个变量 自动匹配类型 var c = 20 // 方法四:省去 var 关键字 自动匹配类型 d := 30 // 多变量写法 var xx, yy int = 50, 60 var kk, ll = 70, "hello" var ( ee int = 10 kk bool = true vv = "hello" )
全局变量
// 除了方法四不支持,其他跟局部变量一致
常量的声明
常量
const a int = 10 const ( b = 10 c = 20 )
iota
// 与 const 配合来表示枚举类型 const ( // 每行的 iota 累加1,第一行默认为0 BEIJING = 10 * iota // 0 SHANGHAI // 10 SHENZHEN // 20 )
函数
多返回值
// 返回多个返回值 (匿名) func hi1(a string, b int) (int, int) { fmt.Println("a = ", a) fmt.Println("b = ", b) return 100, 200 } // 返回多个返回值 (有形参名,默认值为0) // 形参类型相同可简写为 func hi2(a, b string) (r1, r2 int) func hi2(a string, b int) (r1 int, r2 int) { fmt.Println("a = ", a) fmt.Println("b = ", b) r1 = 100 r2 = 200 return }
init函数
说明:项目位于 $GOPATH/src/init
中,如果编译报找不到 std lib1/lib2,可以试试用 go mod init
创建Go模块
// main.go package main import ( "fmt" "init/lib1" "init/lib2" ) func main() { lib1.Lib1Test() lib2.Lib2Test() fmt.Println(lib1.A) }
// lib1/lib1.go package lib1 import "fmt" var A = "你好A" func init() { fmt.Println("lib1 init...") } func Lib1Test() { fmt.Println("lib1 test!") }
// lib2/lib2.go package lib2 import "fmt" func init() { fmt.Println("lib2 init...") } func Lib2Test() { fmt.Println("lib2 test!") }
import导包
// 导入匿名包 fmt,不可使用包内方法,但会执行包内的 init() 方法 import _ "fmt" // 导入别名为 aa 的 fmt 包,可以直接 aa.Println("hi") import aa "fmt" // 将 fmt 包内的方法导入当前包,可以直接 Println("hi") import . "fmt"
指针
package main import "fmt" func swap(a *int, b *int) { temp := *a *a = *b *b = temp } func main() { a := 10 b := 20 swap(&a, &b) fmt.Println("a = ", a, ", b = ", b) }
defer
// 后接的表达式会在方法最后执行,类似 Java 的 finally // 存在多个 defer 时,按先进后出的顺序执行 (Stack) // defer 会在 return 后执行 package main import "fmt" func out1() { fmt.Println("A") } func out2() { fmt.Println("B") } func out3() { fmt.Println("C") } func main() { defer out1() defer out2() defer out3() }
切片slice
数组
package main import "fmt" func printArr(arr [3]int) { // 值传递,printArr::arr 只是 main::arr 的副本 for i := 0; i < len(arr); i++ { fmt.Println(arr[i]) } arr[0] = 11 } func main() { // 数组长度固定 arr := [3]int{1, 2, 3} // 输出 arr 类型,结果为 [3]int fmt.Printf("arr type: %T\n", arr) // 两次输出结果一致 printArr(arr) printArr(arr) }
slice (动态数组)
package main import "fmt" func printArr(arr []int) { // 引用传递,printArr::arr 与 main::arr 所指的内存地址相同 for i := 0; i < len(arr); i++ { fmt.Println(arr[i]) } arr[0] = 11 } func main() { // 动态数组 arr := []int{1, 2, 3} // 输出 arr 类型,结果为 []int fmt.Printf("arr type: %T\n", arr) // 第二次输出 arr[0] 为 11 printArr(arr) printArr(arr) }
slice
// 声明切片,并完成初始化 slice1 := []int{1, 2, 3} // 声明切片,但没有分配空间 var slice2 []int slice2 = make([]int, 3) // 开辟3个空间 // 声明切片,并开辟3个空间 slice3 := make([]int, 3) // 声明一个切片,分配3个长度,5个空间 numbers := make([]int, 3, 5) fmt.Printf("len = %d, cap = %d, slice = %v\n", len(numbers), cap(numbers), numbers) // 往切片里添加一个元素,长度为4,空间为5 numbers = append(numbers, 1) fmt.Printf("len = %d, cap = %d, slice = %v\n", len(numbers), cap(numbers), numbers) // 往切片里添加两个元素,长度为6,空间为10 // 因为5个空间不够,所以需要扩容,扩容数量为初始空间的数量 numbers = append(numbers, 2, 3) fmt.Printf("len = %d, cap = %d, slice = %v\n", len(numbers), cap(numbers), numbers) // 截取切片 numbers2 := numbers[3:5] // [3, 5) numbers3 := numbers[:5] // [0, 5) numbers4 := numbers[3:] // [3, len) fmt.Printf("len = %d, cap = %d, slice = %v\n", len(numbers2), cap(numbers2), numbers2) fmt.Printf("len = %d, cap = %d, slice = %v\n", len(numbers3), cap(numbers3), numbers3) fmt.Printf("len = %d, cap = %d, slice = %v\n", len(numbers4), cap(numbers4), numbers4) // 复制一个切片 numbers5 := make([]int, 10) copy(numbers5, numbers) fmt.Printf("len = %d, cap = %d, slice = %v\n", len(numbers5), cap(numbers5), numbers5
Map
package main import "fmt" func printMap(myMap map[string]string) { // map 是引用传递 for key, value := range myMap { fmt.Printf("key = %s, value = %s\n", key, value) } } func main() { // ===> 声明一个 map[key]value // 方式一: var myMap1 map[string]string myMap1 = make(map[string]string, 5) myMap1["one"] = "java" myMap1["two"] = "c++" myMap1["three"] = "python" fmt.Println(myMap1) // 方式二 myMap2 := make(map[int]string) myMap2[0] = "java" myMap2[1] = "c#" myMap2[2] = "go" fmt.Println(myMap2) // 方式三 myMap3 := map[string]string{ "one": "php", "two": "c#", "three": "java", } // map的使用 printMap(myMap3) myMap3["four"] = "python" // 添加 myMap3["three"] = "go" // 修改 delete(myMap3, "two") // 删除 printMap(myMap3) }
struct
封装
package main import "fmt" type Book struct { title string author string } func changeAuthor(book *Book) { // 结构体默认值传递,需要引用传递需用指针 book.author = "Miss.B" } // 方法绑定到 Book 对象,this 默认值传递,引用传递需用指针 func (this *Book) SetAuthor(newAuthor string) { this.author = newAuthor } func main() { var book1 Book book1.title = "hello" book1.author = "Mr.A" fmt.Println(book1) changeAuthor(&book1) fmt.Println(book1) book1.SetAuthor("Ms.C") fmt.Println(book1) }
继承
package main import "fmt" type Man struct { name string sex int } func (this *Man) Eat() { fmt.Println("Man Eat...") } func (this *Man) Walk() { fmt.Println("Man Walk...") } type Superman struct { Man level int } func (this *Superman) Walk() { fmt.Println("Superman Walk...") } func main() { man := Man{"Mr.A", 19} man.Eat() man.Walk() superman := Superman{Man{"Mr.B", 18}, 100} superman.Eat() superman.Walk() fmt.Println(man) fmt.Println(superman) }
多态
// 基本要素: // 1. 有一个父类 (有接口) // 2. 有子类 (实现了父类的全部接口方法) // 3. 父类指针变量指向子类具体数据 package main import "fmt" // 动物 (父类) type AnimalIF interface { Sleep() GetType() string } // 猫 (子类) type Cat struct { color string } func (this *Cat) Sleep() { fmt.Println("Cat is sleeping...") } func (this *Cat) GetType() string { return "Cat" } // 狗 (子类) type Dog struct { color string } func (this *Dog) Sleep() { fmt.Println("Dog is sleeping...") } func (this *Dog) GetType() string { return "Dog" } func main() { var animal AnimalIF // animal = cat animal = &Cat{"white"} animal.Sleep() fmt.Println(animal.GetType()) // animal = dog animal = &Dog{"Yellow"} animal.Sleep() fmt.Println(animal.GetType()) }
万能数据类型 (空接口)
package main import "fmt" func show(arg interface{}) { fmt.Println(arg) // 类型断言 value, ok := arg.(string) if ok { fmt.Println("arg is string, value is ", value) } else { fmt.Println("arg is not string") } } func main() { show(100) show(3.14) show("hello") }