go入门笔记

由于自己有java,python相关基础,所以没有写的特别详细

学习方向

区块链研发工程师
Go服务器端/游戏软件工程师
golang分布式/云计算软件工程师

学习方向

know how ,在know why

Golang的语言特点

注意事项

以"go" 为扩展名

执行入口是main()函数

严格区分大小写

每个语句后面不带分号

定义的变量和import的包如果没有使用到,代码不能编译通过

shift+tab整体向左移动

使用一个表达式形容Go语言: Go=C+Python

    print()
    println() //print+line
    printf() //print+format
    %T , 打印变量的数据类型
    %d , 打印整数,十进制
    %f , 打印浮点,小数
    %t , 打印字符串
    %s , 打印字符串
    %v , 原样输出
    %c , 打印对应的unicode字符
    %p , 打印地址

变量的定义

  • var 变量 数据类型

    变量名=赋值

  • 缩写成一行

    var 变量名 数据类型=赋值

  • 类型推断

    var 变量名=赋值

  • 省略var

    变量: =赋值

    b:=2 //简短声明不支持全局变量

    在同一区域同一数据类型内不断变化的

    var num int //默认为0 跟js差不多 undefined

_ 只写,不能读

常量

const 常量 数据类型=赋值

const 常量名=赋值

所有的字母大写

如果私有 前加小写字符c

一组常量中,如果某个常量没有初始值,那么默认和上一行一致

iota:计数器 默认为0

    const(
       e=iota
       f
       g
    ) //每当定义一个常量累加1

整型

int uint 和操作系统有关

浮点

float32单精度 float64 双精度

字符串

一个字符byte

Go语言字符使用UTF-8 英文字符1个字节 汉字3个字节

字符串一旦赋值了,就不能在修改

反引号是直接输出``

布尔(bool)

只能取true false不能取0,1 占用一个字节

Go在不同类型的变量之间赋值是需要显式转换,也就是说Golang中数据类型不能自动转换

    var i int32 = 100
        var n1 float32 = float32(i)
        var n2 int8 = int8(i)
        var n3 int64 = int64(i)
        fmt.Print("i=%v n1=%v n2=%v n3=%v", i, n1, n2, n3)
        %v 需要转换的变量

基本数据类型 的默认值

基本类型转string类型

  • fmt.Sprintf 会返回转换后的字符串
  • strconv.FormatFloat
  • strconv.FormatInt
  • strconv.formatbool

string类型转基本数据类型

  • strconv
    ParseInt()
    ParseFloat()
    ParseBool()
    ParseUint()
    n1,_=strconv.ParseInt(str2,10,64)
    f1,_=strconv.ParseFloat(str3,64)

    算术运算符

  • 对于除号"/" 只保留整数部分而舍弃小数部分

Golang的自增自减只能当作一个独立语言使用

例如
i++
i--
++和--只能写在变量的后面,不能写在变量的前面

go 语言明确不支持三元运算符

键盘输入语句

fmt.Scanln() fmt.Scanf()

fmt.scanf可以按照指定的格式输入

fmt.Scanf("%s,%d,%f,%t",&name,&age,&sal,&ispass)

通过&变量保存数据

fmt.Scanln(&name)

    if x>y {
        fmt.Println("true")
    }
    if else  if 
     /*希望函数内的变量能改变函数外的数值,可以传入变量的地址&
       函数内以指针的方式操作变量*/
    func test03(n1 *int) {
       *n1=*n1+10
       fmt.Println("test03 n1=",*n1)
    }
    func main(){
       num:=20
       test03(&num)
       fmt.Println("main() num",num)
    }

go函数不支持重载

自定义数据类型

type 自定义数据类型 数据类型

    type myInt int
    var num1 myInt
    var num2 int
    num1=400
    num2=int(num1)  //这里依然需要显示转换,go认为myInt和int两个类型

argsslice切片,通过args[index] 可以访问各个值

    func sum(n1 int,args... int)int{
       sum:=n1
       for i:=0;i<len(args);i++{
          sum+=args[i]//args[0] 表示取出args切片的第一个元素之
       }
       return sum

    }
    func main(){
       res:=sum(1,2,3,4,5,5,6,6)
       fmt.Println("res=",res)
    }

每一个源文件都可以 包含一个init函数,init会在main函数前调用

执行顺序

bufio包

    reader:=NewReader(os.Stuio)
    reader.ReadLine()====>[]byte
    reader.ReadString('\n')-->String

内置包

math包提供数学计算的函数
math.Abs()

go语言特有

fallthrough 穿透

当某个case匹配成功后执行,如果有fallthrough,那么后面紧邻的case不再匹配,直接执行

    //math/rand包下
    //时间
    t1:=time.Now().Unix()
    fmt.Println(t1)
    //设置种子数
    rand.Seed(t1) //设置获取随机数的种子数
    num1:=rand.Intn(10) //[0,10)
    fmt.Println(num1)

数组

    var arr [4]int
    var b=[4]int{1,2,3,4}
    f:=[...] int{1,2,3,4,5}

    len()  长度
    cap() 容量
    //因为数组是定长的容器,长度和容量是相同的
    range 对数组 取数组的下标和value
    for index,value :=range arr{
       fmt.Println("下标是",index,"数值是",value)
    }
        for _,v :=range arr{
            fmt.Println(v)
        }
    二维数组
    arr:=[4][3]int{{1,2,3},{1,2,3},{1,2,3},{1,2,3}}

切片

    切片slice
    同数组类似,也叫做变长数组
    是一个引用类型的容器,指向了一个底层数据
    因为切片是引用数据的数据,直接拷贝的是地址
    浅拷贝:拷贝的数据地址 copy()
    深拷贝: 拷贝的数据本身
    s2:=[]int{1,2,3,4}
    内置函数
    make()
    s1:=make([] 类型 ,len,cap)  第一个参数:切片的类型,第二个参数:len,第三个参数容量,如果省略,默认跟第二个一样
    ----------------
    s2:=make([] int,3)
        s2=append(s2,1,2,3,4)
    a[start:end] //包左不包右
    当向切片添加数据时,如果没有超过容量,直接添加,如果超过容量,自动扩容(成倍增加)
    /*  数组传递的是数据
            切片传递的是地址*/
        s1:=[] int{1,2,3,4,5}
        fmt.Println(s1)
        s2:=s1
        fmt.Println(s2)
        s2[0]=100
        fmt.Println(s1)
        fmt.Println("--------")
        s3:=[5] int{1,2,3,4,5}
        fmt.Println(s3)
        s4:=s3
        fmt.Println(s4)
        s4[0]=100
        fmt.Println(s4)
        fmt.Println(s3)
    copy copy(s1,s2) 把s2拷贝到s1,但是不会改变长度,能装多少装多少
        s1 := []int{1, 2, 3, 4, 5}
        s2 := []int{6, 7, 8, 9}
        copy(s1,s2)
        fmt.Println(s1)

字符串操作

  • 一个字节的切片

  • strings包下的字符串函数

    strings.Contains() 是否包含指定的内容

    strings.ContainsAny() 是否包含任意一个字符

    Repeat 自己拼接自己count次

    大小写转换 ToLower() ToUpper()

    切割Split() SplitN()
    Index IndexAny

    LastIndex() LastIndexAny()

    Replace(s,old,new,n)

    Trim()

    HasPerfix() 以xx前缀开头

    HasSuffix() 以xx后缀结尾

    查找

    EqualFold不区分大小写的字符串比较

    index 找不到返回-1

    TrimSpace() 将字符串左边两边的空格去掉

    Trim("元字符串",指定要去除的) 将指定的字符串左右两边空格去掉(有区别哦)

    ...

  • 字符串遍历,同时处理有中文的问题 r:[]rune(str)

        str:="hello被"
        r:=[]rune(str)
        for i:=0;i<len(r);i++{
           fmt.Printf("%c\n",r[i])
        }
  • 字符串转整数 n,err=strconv.Atoi("12")

    b:="65"
    s2, _ :=strconv.Atoi(b)
    fmt.Printf("%v",s2)
  • 整数转字符串 str=strconv.Itoa(1234)

  • 字符串 转[]byte: var bytes=[]byte("hello go")

  • []byte转字符串 str=string([]byte{'a','b','c'})

  • 十进制转2,8,16进制str=strconv.FormatInt(123,2)//2->8,16

map, 映射

key ,value 也是一个容器,存储的无序键值对

key不重复,重复就覆盖

map声明是不会分配内存的,初始化需要make,分配内存后才能赋值和使用

类型%T

m:=map[string]int{"one":1,"two":2}
m:=make(map[string]int)
nil 空
将map存进切片中
s1:=make([] map[string]string,0,3)

通过key获取value,当key如果不存在的时候,我们会得到value的默认值

map1[key]=value,根据key获取map中对应的value

value,ok:=map[key] 如果键值对存在,value就是对应的数据,ok为true

如果key不存在获取,获取的是 值的默认值,ok为false,默认key为0

value,ok:=map[key]
f ok{
   fmt.Println("对应的数值是:",v1)
}else{
   fmt.Println("操作的key不存在",vl)
}

内置函数delete

  • delete(map1,key)

sort排序

sort.Ints(key) 字符按照字符串的编码值排序

    str="FKJKJFJdfjakfjakKSKJW"
    map1 := make(map[byte]int)
    for i := 0; i < len(str); i++ {
       val, ok := map1[str[i]]
       if ok {
          val++
       } else {
          val = 1
       }
       map1[str[i]] = val
    }
    keys := make([]byte, 0, len(map1))
    for k := range map1 {
       keys = append(keys, k)
    }
    for _, k := range keys {
       fmt.Printf("%c,%d\n", k, map1[k])
    }
    map1:=make(map[string]map[string]string)
    //需要定义长度
    map1["name"]=make(map[string]string,3)
    map1["liming"]=make(map[string]string,3)
    map1["name"]["name3"]="张三"
    map1["name"]["name1"]="李四"
    map1["name"]["name2"]="王五"
    map1["liming"]["xiaoming1"]="小明"
    map1["liming"]["xiaoming2"]="小红"
    map1["liming"]["xiaoming3"]="小白"
    for k,v :=range map1{
       fmt.Println(k,v)
       for k2,v2:=range v{
          fmt.Println(k2,v2)
       }
    }

time

time.new 获取当前时间

格式化事件fmt.Printf fmt.SPrintf

now:=time.Now()
fmt.Printf("now=%v,now\n",now)
fmt.Printf("%d-%d-%d %d:%d:%d\n",now.Year(),now.Month(),now.Day(),now.Hour(),now.Minute(),now.Second())

time.Format()

fmt.Printf(now.Format("2018-12-12 14:34:23))

Unix() 1970到现在的毫秒值

UnixNano 1970到现在的纳秒值

内置函数

len

new

异常处理

    //使用defer+recover 来捕获异常
    defer func() {
       err := recover() //recover()内置函数,可以捕获到异常
       if err != nil {
          //说明捕获到错误
          fmt.Println("err=", err)
       }
    }()
    errors.New("错误说明") 会返回一个err类型的值表示一个错误

函数

go语言支持函数式编程+面向对象

  • 函数:独立功能,直接调用
  • 方法:对象的功能,对象来调用

可变参数: 参数名...

函数中,可变参数想当于切片

位置参数>可变参数 (顺序)

写返回值的时候,必须在函数上声明返回值的类型

函数式编程

一个函数可以作为另一个函数的参数或返回值

递归函数

自己调用自己

    func getgui(n int) int{
        if n==1||n==2{
            return 1
        }
        return getgui(n-1)+getgui(n-2)
    }

匿名函数

    func(a,b int){
        fmt.Println(a,b)
    }(1,2)

高阶函数(回调函数)

根据go语言函数的数据类型的特点,可以将函数作为另一个函数的参数

    func add(a,b int) int{
       return a+b
    }
    func oper(m,n int,fun func(int,int)int)int{
       res:=fun(m,n)
       return res
    }
    func main() {
       fmt.Println(
          oper(10,20,add))
    }

闭包

引用外部变量的匿名函数

支持将函数作为另一个函数的返回值

    func f(i int) func() int{
       return func() int{
          i++
          return i
       }
    }
    func main() {
       str:=f(10)
       fmt.Println(str())
       fmt.Println(str())
    }
    -----------------------------
    func ExFunc(n int) func () {
        sum:=n
        a:=func(){
            fmt.Println(sum+1)
        }
        return a
    }
    func main() {
        myFunc:=ExFunc(10)
        myFunc()
    }

函数的defer(延时机制)

在执行到defer是,暂时不执行,会将defer后面的压入独立的栈,按照先入后出的方式出栈,执行

先defer再return

获取变量的地址,用&

获取指针类型所指向的值*

fmt.Println(&num)
var ptr *int=&num
值类型,都有对应的指针类型 新式为*数据类型

结构体

    //定义一个类,就是定义一个结构体
    //类的定义,字段属性,行为方法
    type 结构体名称 struct{
        name type
        age int
    }
    //定义结构体变量
        var p1 结构体名称
        p2:=Person{"mary",20}

        p6:=new(Person)
        var p1 Person
        p1.Age=10
        p1.Name="小明"
        var p2 *Person=&p1
        fmt.Println((*p2).Age)
        注意不能*p2.Age写,因为.的优先级比* 高

    // 实现结构体的浅拷贝
        d4:=new(dog)
        d4.color="黄色"
        d4.age=2
        d4.kind="中华田园犬"
        fmt.Println(d4)
        d5:=d4
        d5.kind="张三"
        fmt.Println(d5,d4)
        d6:=&d1//*dog
        d6.kind="金毛"
        fmt.Println(d6,d1)
    //匿名结构体:没有名字的结构体,在创建匿名结构体,同时创建对象
        p1:=struct {
            name string
            age  int
        }{
            name: "zhangsan",
            age:  30,
        }
    //匿名字段
        type student struct{
        string
        int//匿名字段(不能有重复字段)
        }
        s1:=student{"zhgsan",12}
        fmt.Println(s1.string,s1.int)
        type Book struct{
        bookName string
        price float64
        auther string
    }
    //嵌套struct的名称冲突
    有以下两个名称冲突的规则(报错)
    * 外部struct覆盖内部struct的同名字段,同名方法(1)
    * 同级别的struct出现同名字段,方法将报错(2)
        type A struct{
        a int
        b int
        }
        type B struct{
            b int
            c string
            d string
        }
        type C struct {
            A  //继承
            B
            a string
            c string
        }
        (1) C.a和C.c分别覆盖A.a和B.c
        (2) A.b和B.b
        为什么呢? 继承的"提升字段"
    //结构体嵌套
    //模拟面向对象:聚合关系
    //一个类作为另一个类的属性
        //定义一个书的结构体
        type Book struct{
            bookName string
            price float64
            auther string
        }
        //定义一个人的结构体
        type Person struct{
            name string
            age int
            book Book  //聚合
        }

        func main() {
            p3:=Person{
                name:"Jerry",
                age:26,
                book:Book{
                    bookName:"Go语言是怎么练成的",
                    price:55.0,
                    auther:"张三",
                },
            }
            fmt.Println(p3.book.auther,p3.book.price,p3.book.auther)
            p4:=Person{"李晓华",20,Book{"四万个为什么",44.8,"张三"}}
            fmt.Println(p4.book.auther,p4.book.price,p4.book.auther)
        }
  • struct 的数据类型:值类型:默认深拷贝
  • 如果结构体的字段类型是:指针,slice,和map的零值都是nil,还没有分配空间
  • 如果需要使用这样的字段 ,需要先make,才能使用
  • 结构体是值类型

猜你喜欢

转载自www.cnblogs.com/fangdongdemao/p/10046211.html