Go语言入门

学习

Go 语言入门

1. 运行环境安装

中文网

安装 VSCODE 后进行环境变量设置代理

教程

示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
package main  // 程序包名称

import "fmt"

//main函数

func main(){

	fmt.Println("halo go")

}

终端

1
2
3
4
5
go run hello.go

go build hello.go //生成二进制文件

./hello.go //生成二进制文件

注意点

  • 分号结尾不影响使用
  • 函数的{和函数名同一行不然报错
  • 注释用//和/* */
  • fmt 中 Println 空一行,Printf 表示格式化输出,%s 表示原字符,%T 表示类型,Sprintf(格式,变量)

2. 基础语法

无效标识符

  • 以数字开头
  • Go 语言关键字
  • 运算符

导入包

  • 方法名需要首字母大写,否则只能在包内调用
  • 导入包不使用会报错,前面加上_无法调用会执行内部 init 方法,起别名可直接调用,加上.可以调用全部方法

变量声明

  • 已被声明的变量不能再次声明
  • _被用来抛弃值
  • &返回地址,*指针变量
  • 全局变量只能用普通方法声明,常用:=
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
package main

import (
	"fmt"
)

// 声明变量四种方式
var gA int = 100

func main() {

	//声明全局变量前三种没问题,第四种只能在函数体内声明
	var a int //默认值0
	fmt.Println("a = ", a)
	fmt.Printf("a = %T\n", a)

	var b int = 100
	fmt.Println("b = ", b)
	fmt.Printf("b = %T\n", b)

	//不声明类型直接赋值
	var c = 100
	fmt.Println("c = ", c)
	fmt.Printf("c = %T\n", c)

	var d string = "abcd"
	fmt.Println("d = ", d)
	fmt.Printf("d = %T\n", d)

	//先初始化在赋值
	e := 100
	//fmt.Printf("e = %s, type of e = %T\n", e, e)
	fmt.Println("e = ", e)
	fmt.Printf("e = %T\n", e)

	fmt.Println("gA = ", gA)

	//声明多个变量
	var xx, yy int = 100, 200
	fmt.Println("xx = ", xx, ", yy = ", yy)

	var (
		aa = 100
		bb = 200
	)
	fmt.Println("aa = ", aa, ", bb = ", bb)

}

数据类型

常量

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
package main

import (
	"fmt"
)

const (
	//const里通过iota,每行累加1,第一行默认0, 枚举
	Beijing = iota //0
	Shanghai
	Shenzhen
)

func main() {
	//常量(只读)
	const length int = 10
	fmt.Println("length = ", length)
	fmt.Println("Beijing = ", Beijing)
	fmt.Println("Shanghai = ", Shanghai)
	fmt.Println("Shenzhen = ", Shenzhen)
}

多个返回值,形参

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package main

import (
	"fmt"
)

// 匿名形参
func foo1(a string, b int) (int, int) {
	fmt.Println("a = ", a)
	fmt.Println("b = ", b)
	return 666, 777
}

// 有名形参,可以写成(r1, r2 int)
func foo2(a string, b int) (r1 int, r2 int) {
	fmt.Println("a = ", a)
	fmt.Println("b = ", b)
	r1 = 1000
	r2 = 2000
	return
}

func main() {
	ret1, ret2 := foo1("haha", 999)
	fmt.Println("ret1 = ", ret1, "ret2 = ", ret2)

	ret1, ret2 = foo2("foo2", 222)
	fmt.Println("ret1 = ", ret1, "ret2 = ", ret2)
}

指针

1666571229002

1666571973317

条件判断补充

switch 自带 break,继续执行 case 加 fallthrough,default 默认运行

select

defer 函数

  • 相当于 final,函数结尾执行,以压栈的方式先入后出
  • defer 和 main,return 函数比 defer 先执行

数组

固定大小,传参传值

1
var myArray1 [10]int

动态数组传参传指针,引用

1
myArray = []int{1,2,3,4}

切片四种方式,声明切片但是不分配空间

1
2
3
4
5
6
7
slice1 := []int{1,2,3}

var slice1 []int \\ slice1 = make([int,3])

var slice []int = make([]int,3)

slice1 := make([]int, 3)

nil 空

len 长度,cap 容量

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
package main
import "fmt"

func main() {
	s := []int{1, 2, 3}
	s1 := s[0:2]		//S和s1指向同个空间
	s1[0] = 100
	fmt.Println(s)  	//[100 2 3]
	fmt.Println(s1)		//[100 2]

	s2 := make([]int, 3)
	copy(s2, s)			//s2复制s指向新的空间
	fmt.Println(s2)		//[100 2 3]
	s2[0] = 1000
	fmt.Println(s)
	fmt.Println(s1)
	fmt.Println(s2)
}

map

map3 种声明方式

1667013600495map 的方法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package main

import "fmt"

func printMap(cityMap map[string]string) {
	//cityMap引用传递
	for key, value := range cityMap {
		fmt.Println("key = ", key)
		fmt.Println("value = ", value)
	}
}

func ChangeValue(cityMap map[string]string) {
	cityMap["England"] = "London"
}

func main() {
	cityMap := make(map[string]string)

	//添加
	cityMap["China"] = "Beijing"
	cityMap["Japan"] = "Tokyo"
	cityMap["USA"] = "NewYork"

	//遍历
	printMap(cityMap)

	//删除
	delete(cityMap, "China")

	//修改
	ChangeValue(cityMap)

	fmt.Println("------")

	//遍历
	printMap(cityMap)
}

结构体

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package main

import "fmt"

type Book struct {
	title string
	auth  string
}

func changeBook(book Book) {
	//指针传递
	book.auth = "666"
}

func changeBook2(book *Book) {
	//指针传递
	book.auth = "777"
}

func main() {
	var book1 Book
	book1.title = "Golang"
	book1.auth = "zhuang3"

	fmt.Printf("%v\n", book1)
	changeBook(book1)
	fmt.Printf("%v\n", book1)
	changeBook2(&book1)
	fmt.Printf("%v\n", book1)

}

类方法

大写字母开头的方法是公有,小写是私有

类定义的方法 func(副本 *结构体) 类方法名()类型{}

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package main

import "fmt"

type Hero struct {
	Name  string
	Ad    int
	level int //私有变量
}

func (this *Hero) Show() {
	fmt.Println("Name= ", this.Name)
	fmt.Println("Ad= ", this.Ad)
	fmt.Println("Level= ", this.level)
}

func (this *Hero) GetName() string {
	return this.Name
}

func (this *Hero) SetName(newName string) {
	this.Name = newName
}

func main() {
	hero := Hero{Name: "zhang3", Ad: 100, level: 1}

	hero.Show()

	hero.SetName("li4")

	hero.Show()
}

父类与子类 继承

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
package main

import "fmt"

type Hero struct {
	name string
	sex  string
}

func (this *Hero) Show() {
	fmt.Println("name= ", this.name)
}

func (this *Hero) Getname() string {
	return this.name
}

func (this *Hero) Setname(newname string) {
	this.name = newname
}

type SuperMan struct {
	Hero  //继承Hero类方法
	level int
}

func (this *SuperMan) Eat() {
	fmt.Println("SuperMan.Eat()...")
}

func (this *SuperMan) Fly() {
	fmt.Println("SuperMan.Fly()...")
}

func (this *SuperMan) Print() {
	fmt.Println("name= ", this.name)
	fmt.Println("sex= ", this.sex)
	fmt.Println("level= ", this.level)
}

func main() {
	hero := Hero{"zhang3", "female"}

	hero.Show()
	hero.Setname("li4")
	hero.Show()

	//s := SuperMan{Hero{"li4", "female"}, 88}	//容易重复
	var s SuperMan
	s.name = "li4"
	s.sex = "male"
	s.level = 88
	s.Show()
	s.Fly()
	s.Print()
}

多态与接口

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
package main

import "fmt"

type AnimalIF interface { //父类接口
	Sleep()
	GetColor() string
	GetType() string
}

type Cat struct { //子类
	color string
}

func (this *Cat) Sleep() { //定义父类方法
	fmt.Println("Cat is Sleep")
}

func (this *Cat) GetColor() string { //报错返回值过多
	return this.color
}

func (this *Cat) GetType() string {
	return "Cat"
}

type Dog struct {
	color string
}

func (this *Dog) Sleep() {
	fmt.Println("Dog is Sleep")
}

func (this *Dog) GetColor() string {
	return this.color
}

func (this *Dog) GetType() string {
	return "Dog"
}

func showAnimal(animal AnimalIF) {
	animal.Sleep()
	fmt.Println("color = ", animal.GetColor())
	// fmt.Println("type = ", animal.GetType())
}

func main() {
	// var animal AnimalIF
	// animal = &Cat{"Green"}	赋值,父类接口指针指向子类的具体对象,再用父类调用接口
	// animal.Sleep()
	// animal = &Dog{"Yellow"}
	// animal.Sleep()
	cat := Cat{"Green"}
	dog := Dog{"Yellow"}
	showAnimal(&cat)
	showAnimal(&dog)
}

万能通用接口

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package main

import "fmt"

func myFunc(arg interface{}) { //通用万能类型 空接口
	fmt.Println("myFunc is called")
	fmt.Println(arg)
	//interface{}区分底层数据类型,可以用类型断言arg.(string)
	value, ok := arg.(string)
	if !ok {
		fmt.Println("arg is not string type")
	} else {
		fmt.Println("arg is string type, value = ", value)

		fmt.Printf("value type is %T\n", value)
	}
}

type Book struct {
	auth string
}

func main() {
	book := Book{"Golang"}
	myFunc(book)
	myFunc(100)
	myFunc("abc")
}

断言

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
package main

import (
	"fmt"
)

func main() {
	var a int
	//pair<statictype:string, value:"aceld">
	// a = "aceld"
	a = 123
	//pair<type:string, value:"aceld">
	var allType interface{}
	allType = a

	str, st := allType.(string)
	fmt.Println(str)
	fmt.Println(st)
}

reflect

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
package main

import (
	"fmt"
	"reflect"
)

type User struct {
	Id   int
	Name string
	Age  int
}

func (this User) Call() {
	fmt.Println("user is called")
	fmt.Printf("%v\n", this)
}

func main() {
	user := User{1, "Aceld", 18}

	DoFileAndMethod(user)
}

func DoFileAndMethod(input interface{}) {
	//获取input的type
	inputType := reflect.TypeOf(input)
	fmt.Println("inputType is :", inputType.Name())

	//获取input的value
	inputValue := reflect.ValueOf(input)
	fmt.Println("inputValue is :", inputValue)

	//通过type 获取里面的字段
	//1. 获取interface的reflect.Type, 通过Type得到NumField,进行遍历
	//2. 得到每个filed, 数据类型
	//3. 通过 filed有一个Interface() 方法等到对应的value
	//通过type 获取里面的方法,调用
	for i := 0; i < inputType.NumField(); i++ {
		field := inputType.Field(i)
		value := inputValue.Field(i).Interface()

		fmt.Printf("%s: %v = %v\n", field.Name, field.Type, value)
	}
	//通过type 获取里面的方法,调用
	for i := 0; i < inputType.NumMethod(); i++ {
		m := inputType.Method(i)
		fmt.Printf("%s: %v\n", m.Name, m.Type)
	}
}

reflect 中的 tag 标签

最后更新于 05月19日 12点44分, 2026年