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")
}