-
go build vs go run
image.png
-
一个project只能有一个main包
-
go不用分号
-
go
//go的基本格式
package main
import "fmt"
func main(){
}



-
Printf PrintIn
image.png
-
多重赋值和匿名变量
image.png
-
多个变量常量定义
image.png
-
iota枚举(只用于常量)
image.png
image.png
-
bool
image.png
-
float
image.png
-
ASCII码
image.png
-
字符串类型
image.png
-
字符和字符串区别(字符是以数字存储的,所以字符的数据类型是int)
image.png
-
复数类型
image.png
-
格式化输出
%T
image.png
image.png
image.png
-
输入的使用
image.png
-
类型转换
image.png
-
类型别名
image.png
-
运算符
image.png
/,取商
%,取余,取模
8/5 = 1
8%5 = 3
3/4 = 0
3%4 = 3
7/3 = 2
7%3 = 1
2/1 = 2
2%1 = 0
-
if
image.png
-
if else
image.png
-
switch
image.png
image.png
image.png
image.png
-
for循环(go没有while和do while)
image.png
-
range(迭代)
image.png
-
break 和 continue
break可以用于for switch和select,continue只能用于循环
image.png
- goto
-
函数(函数的顺序无所谓)
image.png
image.png
-
不定参数(args...type)
image.png
//一个函数里可以同时传固定参数和不定参数
func Myfunc03(a int, args ...int) {
}
func main () {
MyFunc03(111,1,2,3)
}
//不定参数的传递
func myfunc(tmp ...int){ //注意要有空格
for _, data := range tmp {
fmt.PrintIn("data=", data)
}
}
func test(args ...int){
myfunc(args...) //把全部不定参数传递给myfunc
myfunc(args[:2]...) //把arg[2]之前(不包括arg[2]的所有参数传递给myfunc
myfunc(args[2:]...) //从arg[2]开始(包括arg[2])把后面所有参数传递给myfunc
}
func main(){
test(1,2,3,4)
}
- 返回值
写在func myfunc() 这里是返回值 {}
package main
import fmt
//返回值基础写法
func myfunc() int {
return 666
}
//返回值常用写法/go推荐写法(给返回值取名并赋值)
func myfunc1() (result int) {
result = 666
return
}
func main(){
a := myfunc()
fmt.PrintIn("a=", a)
b := myfunc1()
fmt.PrintIn("b=", b)
}
//多个返回值写法,go推荐写法
func myfunc2() (a,b,c int) {
a,b,c = 111,222,333
return
}
func main(){
a,b,c := myfunc2()
fmt.Printf("a=%d, b=%d, c=%d\n",a,b,c)
}
- 有参有返回值
func myfunc(a,b int) (max,min int) {
if a>b {
max = a
min = b
}else{
max = b
min = a
}
return
}
func main(){
max,min := myfunc(10,20)
fmt.Printf("max = %d, min = %d\n",max,min)
//通过匿名变量丢弃某个返回值
a,_ := myfunc(30,40)
fmt.Printf("a = %d\n",a)
}
-
普通函数调用流程(先调用完成,再逐一打印)
image.png
-
递归函数的调用流程
image.png
- 数字累加
//实现1+2+3+...100
//普通函数方法
func funca () {
for var i=1,i<=100,i++ {
sum += i
}
return
}
func main () {
var sum int
sum = funca()
fmt.PrintIn("sum=",sum)
}
//递归函数方法
//100+99+98+...1
func funcb (i int) int {
if i = 100 {
return 100
}
return i + funcb(i+1)
}
//1+2+3+...100
func funcc (i int) int {
if i = 1 {
return 1
}
return i + funcc(i-1)
}
func main () {
var sum1,sum2 int
sum1 = funcb(1)
sum2 = funcc(100)
fmt.PrintIn("sum=",sum)
}
- 函数类型 & 回调函数
回调函数就是参数里面有函数
package main
import "fmt"
//为FuncType(自定义名称)定义类型为函数,两个int参数,一个int返回值
type FuncType func(int,int) int
func Add (a,b int) int {
return a+b
}
func Minus(a,b int) int {
return a-b
}
func Mul(a,b int) int {
return a*b
}
func Calc(a,b int, fTest FuncType) (result int) {
result = fTest(a,b)
return
}
func main () {
a := Calc(1,2,Add)
fmt.PrintIn("a=",a)
b := Calc(3,4,Mul)
fmt.PrintIn("b=",b)
}
- 匿名函数
package main
import "fmt"
func main () {
a := 10
str := "mike"
//定义匿名函数同时调用(无参无返回值)
fanc () {
fmt.Printf("a=%d, str=%s\n",a,str)
}()
//带参数的匿名函数
f1 := func (i,j int) {
fmt.Printf("i = %d, j = %d\n",i,j)
}
f1(1,2)
//带参数匿名函数自调用
func () {
fmt.Printf("i = %d, j = %d\n",i,j)
} (1,2)
//匿名函数(有参有返回值)
ma,mi := func (i,j int) (max,min int) {
if i>j {
max = i
min = j
}else{
max = j
min = i
}
return
} (1,2)
fmt.Printf("max = %d, min = %d\n",ma,mi)
}
-
闭包(调用了外部变量的函数)
image.png
闭包以引用方式捕获外部变量(函数内部可以读取和修改外部变量)
func main () {
a := 10
str := "mike"
func () {
a := 20
str := "go"
fmt.Printf("a = %d, str = %s\n",a,str) //输出 20 go
} ()
fmt.Printf("a = %d, str = %s\n",a,str) //输出 20 go
}
没有闭包调用,函数调用完毕,内部变量自动释放:
func test () int {
//函数被调用时,x才分配空间,才初始化为0
var x int //未初始化,值为0
x++
return x * x //函数调用完毕,x自动释放
}
func main () {
fmt.PrintIn(test()) //输出1
fmt.PrintIn(test()) //输出1
fmt.PrintIn(test()) //输出1
}
有闭包调用,内部变量不释放:
func test1() func() int { //test1()返回一个函数func(),函数func()返回一个int
var x int
return func() int {
x++
return x*x
}
}
func main() {
f := test1()
fmt.PrintIn(f()) //输出1
fmt.PrintIn(f()) //输出4
fmt.PrintIn(f()) //输出9
}
- defer (加了defer的语句会在函数结束前的瞬间执行)
//先输出bbbbb,再输出aaaaa
func main() {
defer fmt.PrintIn("aaaaa")
fmt.PrintIn("bbbbb")
}
多个defer(last in first out)

func test (x int) {
result := 100 / x
fmt.PrintIn(result)
}
//先输出aaaaa,再输出bbbbb,再输出错误消息,不再执行ccccc语句
func main() {
fmt.PrintIn("aaaaa")
fmt.PrintIn("bbbbb")
test(0)
fmt.PrintIn("ccccc")
}
//先输出ccccc,再输出bbbbb,再输出aaaaa,最后是错误消息
func main() {
defer fmt.PrintIn("aaaaa")
defer fmt.PrintIn("bbbbb")
defer test(0)
defer fmt.PrintIn("ccccc")
}
- defer结合匿名函数
func main() {
a := 10
b := 20
defer func () {
fmt.Printf("a = %d, b = %d\n",a,b) //后输出 111 222
}
a = 111
b = 222
fmt.Printf("外部:a = %d, b = %d\n",a,b) //先输出 111 222
}
func main() {
a := 10
b := 20
defer func (a,b int) {
fmt.Printf("a = %d, b = %d\n",a,b) //后输出 10 20 已经先传递参数,只是没有调用
} (a,b)
a = 111
b = 222
fmt.Printf("外部:a = %d, b = %d\n",a,b) //先输出 111 222
}
- 局部变量
定义在{}里的变量就是局部变量,只在{}里面有效(也包括if条件语句中的变量)
执行到定义变量的那句话才开始分配空间,离开作用域自动释放
func test() {
a := 10
fmt.PrintIn("a=",a)
}
func main() {
a = 111 //报错,a undefined
{
i :=10
fmt.PrintIn("i=",i)
}
i = 111 //报错,i undefined
if flag := 3; flag ==3 {
fmt.PrintIn("flag=",flag)
}
flag = 4 //报错,flag undefined
}
- 全局变量:定义在函数外部的变量,全局都可以使用
- 不同作用域,允许定义同名变量
使用变量的原则,就近原则
var a byte
func main() {
var a int
fmt.Printf("%T\n",a) //int
test() //unit8,就是byte
}
func test() {
fmt.Printf("%T\n",a)
}
-
复合类型
image.png
-
指针
image.png
image.png
image.png
-
new函数
image.png
image.png
值传递:image.png
地址传递:image.png
- 数组
//数组的长度必须是常量,且是类型的组成部分。[2]int和[3]int是不同类型。
var a [n]int //err
n := 10
var b [n]int //err 不是常量
var c [10]int //ok
fmt.Printf("len(c)=", len(c)) //10
//赋值
for c := 0; i<len(c);i++ {
c[i] = i+1
}
for i,data := range c {
fmt.Printf("i=%d, data=%d\n",i,data)
}
//如果忽略 [] 中的数字不设置数组大小,Go 语言会根据元素的个数来设置数组的大小:
var balance = [...]float32{1000.0, 2.0, 3.4, 7.0, 50.0}
//数组的下标可以是变量或常量
i := 1
a[i] = 2
//数组初始化(声明定义同时赋值叫初始化)
//全部初始化
var a [5]int = [5]int{1,2,3,4,5}
b := [5]int{1,2,3,4,5}
fmt.PrintIn("a=",a) //[1 2 3 4 5]
fmt.PrintIn("b=",b) //[1 2 3 4 5]
//部分初始化,没有初始化的部分,自动赋值为0
c := [5]int{1,2,3}
fmt.PrintIn("c=",c) //[1 2 3 0 0]
//指定某个元素初始化
d := [5]int{2:10, 4:20}
fmt.PrintIn("d=",d) //[0 0 10 0 20]
//数组的比较 只支持==和!=,比较是不是每一个元素都一样,数组类型要一样
a := [5]int{1,2,3,4,5}
b := [5]int{1,2,3,4,5}
c := [5]int{1,2,3}
fmt.PrintIn("a==b", a==b) //true
fmt.PrintIn("a==c", a==c) //false
//同类型数组可以赋值
var e [5]int
e = a
fmt.PrintIn("e=", e) //{1,2,3,4,5}
二维数组
a := [3][4]int{{1,2,3,4}, {5,6,7,8}, {9,10,11,12}}
//部分初始化,没有初始化的部分,自动赋值为0
b := [3][4]int{{1,2,3}, {5,6,7,8}, {9,10}}
c := [3][4]int{{1,2,3,4}, {5,6,7,8}} //{{1,2,3,4}, {5,6,7,8}, {0,0,0,0}}
//指定某个元素初始化
d := [3][4]int{1: {5,6,7,8}
//循环写二维数组
var e [3][4]int
k := 0
for i := 0; i<3; i++ {
for j := 0; j<4; j++ {
k++
e[i][j] = k
}
}
fmt.PrintIn("e=",e) //{{1,2,3,4}, {5,6,7,8}, {9,10,11,12}}
- 随机数
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
//rand.Seed(666) //固定seed数,每次运行程序产生的随机数都是一样的
rand.Seed(time.Now().UnixNano()) //以当前系统时间作为随机数,每次运行产生的数不一样
for i := 0; i < 5; i++ {
//fmt.Println("rand=", rand.Int()) //随机很大的数
fmt.Println("rand=", rand.Intn(100)) //控制在100以内的数
}
}
-
数组做函数参数
image.png
数组指针做函数参数image.png
-
切片slice
image.png
image.png
image.png
切片创建image.png
切片和底层数组的关系:image.png
- 切片作为函数参数传递,传递的是路径,而不仅仅是复制,所以会改变原有形参
-
切片截取
image.png
-
append
image.png
image.png
image.png
-
copy
image.png
-
map
map创建:
image.png
map赋值;image.png
map遍历:image.png
map删除一个键值:image.png
map做函数参数,是引用传递:image.png
-
结构体
image.png
结构体普通变量初始化image.png
结构体指针变量初始化image.png

结构体比较和赋值

结构体作为函数参数传递


-
go语言可见性规则
image.png
-
深浅拷贝
image.png
//深拷贝
a := 10
b := a //深拷贝
fmt.PrintIn(a,b) //10,10
b = 20
fmt.PrintIn(a,b) //10,20
arr1 := [4]int{1,2,3,4}
//深拷贝
arr2 := arr1
arr2[0]{100}
//浅拷贝
arr3 := &arr1
(*arr3)[0] = 200 //理论的写法
arr3[0] = 200 //go的语法糖
网友评论