go

作者: 嘤嘤嘤998 | 来源:发表于2019-04-30 14:04 被阅读0次
  • go build vs go run image.png
  • 一个project只能有一个main包

  • go不用分号

  • go

//go的基本格式
package main
import "fmt"
func main(){

}
image.png image.png image.png
  • 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) image.png
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
结构体成员的使用——普通变量: 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的语法糖


相关文章

网友评论

      本文标题:go

      本文链接:https://www.haomeiwen.com/subject/qhrdnqtx.html