• Go语言学习笔记


    变量名由字母、数字、下划线组成,不能以数字开头。

    var (
        A int    //默认为0
        B string //默认为""
        C bool   //默认为false
    
        Name string = "suoning"
        Age         = 18 // 自动识别类型
    )
    
    func main() {
        sex := "man"          //等价于 var sex string = "man"
        var girlfriend string //声明变量
        girlfriend = "Dawn"   //变量赋值
    
        Name := "Nick" //正确
        //girlfriend := "Jenny"    //错误的!不能申明两次
        ...
    }

    常量使用const 修饰,代表永远是只读的,不能修改。

    常量中的数据类型只可以是布尔型、数字型(整数型、浮点型和复数)和字符串型。

    语法:const identifier [type] = value,其中type可以省略。

    iota

    iota,特殊常量,可以认为是一个可以被编译器修改的常量。

    在每一个const关键字出现时,被重置为0,然后再下一个const出现之前,每出现一次iota,其所代表的数字会自动增加1。

    const (
        A = 'a'    //97
        B = iota   //1
        C          //2
        D = "nick" //"nick"  iota += 1
        E          //"nick"  iota += 1
        F = 618    //618  iota +=1
        G          //618  iota +=1
        H = iota   //7
        I          //8
    )

    基本数据类型

    布尔型的值只可以是常量 true 或者 false。

    数字类型

    int:

    • uint8(无符号 8 位整型 (0 到 255))
    • uint16(无符号 16 位整型 (0 到 65535))
    • uint32(无符号 32 位整型 (0 到 4294967295))
    • uint64(无符号 64 位整型 (0 到 18446744073709551615))
    • int8(有符号 8 位整型 (-128 到 127))
    • int16(有符号 16 位整型 (-32768 到 32767))
    • int32(有符号 32 位整型 (-2147483648 到 2147483647))
    • int64(有符号 64 位整型 (-9223372036854775808 到 9223372036854775807))

    float:

    • float32(IEEE-754 32位浮点型数)
    • float64(IEEE-754 64位浮点型数)
    • complex64(32 位实数和虚数)
    • complex128(64 位实数和虚数)

    其它:

    • byte(类似 uint8)
    • rune(类似 int32)
    • uint(32 或 64 位)
    • int(与 uint 一样大小)
    • uintptr(无符号整型,用于存放一个指针) 

    字符类型

    存储为ascii码

    var a byte = 'a'
    fmt.Println(a)    //97

    字符串类型

    字符串表示两种方式:

    双引号 

    `` (反引号,不转义)

    string底层就是一个byte的数组

    string本身是不可变的,因此要改变string中字符,需要如下操作:

    str := "hello world"

    s := []byte(str)

    s[0] = 'o'

    str = string(s)

    If/else & for & range

    注意 else if / else 位置

    if condition1 {

    } else if condition2 {

    } else if condition3 {

    } else {

    }

    for循环条件没有小括号

    for i := 0; i < 10; i++ {

    }

    死循环

    for true {

    }

    可以简写为:

    for {

    }

    range

    for i, v := range str {

    }

    package main

    import (

        "fmt"

    )

    func ran(str string) {

        for i, v := range str {

            fmt.Printf("index[%d] val[%c] len[%d] ", i, v, len([]byte(string(v))))

        }

    }

    func main() {

        ran("Love, 索宁")

    }

    switch case

    Go里面switch默认相当于每个case最后带有break,匹配成功后不会自动向下执行其他case,而是跳出整个switch。

    func sw(num int) {
        switch num {
        case 1, 2, 3:
            fmt.Printf("%s in 1,2,3
    ", num)
        case 4, 5, 6:
            fmt.Printf("%s in 4,5,6
    ", num)
            fallthrough
        case 7, 8, 9:
            fmt.Printf("%s big 789
    ", num)
        default:
            fmt.Printf("default...
    ")
        }
    }

    main & init & defer

    main & init

    init() 方法是在任何package中都可以出现;
    main() 方法只能用在package main 中。
    Go程序会自动调用init()和main(),所以你不需要在任何地方调用这两个函数。
    每个package中的init函数都是可选的,但package main就必须包含一个main函数。
    main()函数不能带参数,也不能定义返回值。命令行传入的参数在os.Args变量中保存。如果需要支持命令行开关,可使用flag包。 
     

    defer

    1. 当函数返回时,执行defer语句;
    2. 多个defer语句,按先进后出的方式执行;
    3. defer语句中的变量,在defer声明时确定变量
    4. 触发异常也会走defer语句。
    package main
    
    import "fmt"
    
    //声明defer时,变量i就为0
    func test1()  {
        i := 0
        defer fmt.Println(i)
        i++
        return
    }
    
    //栈,先进先出
    func test2()  {
        for i := 0; i < 5; i++ {
            defer fmt.Printf("->%d", i)
        }
    }
    
    func main() {
        test1()
        test2()
    }

    闭包

    闭包是一个函数和与其相关的引用环境组合而成的实体。

    函数可以存储到变量中作为参数传递给其它函数,能够被函数动态的创建和返回。

    func Adder() func(int) int {
        var x int
        return func(d int) int {
            x += d
            return x
        }
    }
    
    f := Adder()
    fmt.Println(f(1))    //1
    fmt.Println(f(10))    //11
    fmt.Println(f(100))    //111

    值传递 & 引用传递

    无论是值传递,还是引用传递,传递给函数的都是变量的副本;

    值传递是值的拷贝,引用传递是地址的拷贝;

    一般来说,地址拷贝更为高效。而值拷贝取决于拷贝的对象大小,对象越大,则性能越低。

    map、slice、chan、指针、interface默认以引用的方式传递。

    new 内置函数 用来分配内存,主要用来分配值类型,比如int、struct,返回的是指针;

    make 内置函数 用来分配内存,主要用来分配引用类型,比如chan、map、slice。

     

    程序初始化与执行过程

    程序的初始化和执行都起始于main包。
    如果main包还导入了其它的包,那么就会在编译时将它们依次导入。
    有时一个包会被多个包同时导入,那么它只会被导入一次(例如很多包可能都会用到fmt包,但它只会被导入一次,因为没有必要导入多次)。
    当一个包被导入时,如果该包还导入了其它的包,那么会先将其它包导入进来,然后再对这些包中的包级常量和变量进行初始化,接着执行init函数(如果有的话),依次类推。
    等所有被导入的包都加载完毕了,就会开始对main包中的包级常量和变量进行初始化,然后执行main包中的init函数(如果存在的话),最后执行main函数。
     

     

    指针类型(&*)  

    普通类型,变量存的就是值,也叫值类型;

    指针类型,变量存的是一个地址,这个地址存的才是值。

    变量是一种占位符,用于引用计算机内存地址;

    Go 语言的取地址符是 &,放到一个变量前使用就会返回相应变量的内存地址。

    获取指针类型所指向的值,使用:*。

     

    一个指针变量可以指向任何一个值的内存地址它指向那个值的内存地址。

    申明如下:

    var age *int           //指向整型
    var height *float32    //指向浮点型

    当一个指针被定义后没有分配到任何变量时,它的值为 nil。

    nil 指针也称为空指针。

     

    栗子

    package main
    
    import "fmt"
    
    func main() {
        var ptr *int
        num := 100
        ptr = &num
        fmt.Println(ptr)    //0xc42000e1f8
        fmt.Println(*ptr)   //100
        *ptr = 200
        fmt.Println(num)    //200
    }


    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
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    package main;
     
    import (
        "time"
        "fmt"
    )
     
    func main() {
        //time.Time代表一个纳秒精度的时间点
        var t time.Time;
        //返回当前时间
        t = time.Now();
        fmt.Printf("%v ", t);
        //反回所在时区
        fmt.Printf("%v ", t.Location());
        //返回UTC时间和UTC时区
        fmt.Printf("%v %v ", t.UTC(), t.UTC().Location());
        //同上,In()返回指定时区的时间
        fmt.Printf("%v %v ", t.In(time.UTC), t.In(time.UTC).Location());
        //返回当地时区的时间
        fmt.Printf("%v %v ", t.Local(), t.Local().Location());
     
        //根据时间戳返回本地时间
        //参数分别表示秒数和纳秒数
        t2 := time.Unix(1487780010, 0);
        fmt.Println(t2);
     
        //根据指定时间返回time.Time
        //分别指定年,月,日,时,分,秒,纳秒,时区
        t3 := time.Date(2017, time.Month(5), 26, 15, 30, 20, 0, t.Location());
        fmt.Println(t3);
     
        //格式化输出时间
        t4 := time.Now();
        fmt.Println(t4.Format("2006-01-02 15:04:05"));
     
        //获取时间信息
        t5 := time.Now();
        //返回日期
        fmt.Println(t5.Date());
        //返回年
        fmt.Println(t5.Year());
        //返回月
        fmt.Println(t5.Month());
        //返回日
        fmt.Println(t5.Day());
        //返回星期
        fmt.Println(t5.Weekday());
        //返回ISO 9601标准下的年份和星期编号
        fmt.Println(t5.ISOWeek());
        //返回时分秒
        fmt.Println(t5.Clock());
        //返回小时
        fmt.Println(t5.Hour());
        //返回分钟
        fmt.Println(t5.Minute());
        //返回秒
        fmt.Println(t5.Second());
        //返回纳秒
        fmt.Println(t5.Nanosecond());
        //返回一年中对应的天
        fmt.Println(t5.YearDay());
        //返回时区
        fmt.Println(t5.Location());
        //返回时区的规范名,时区相对于UTC的时间偏移量(秒)
        fmt.Println(t5.Zone());
        //返回时间戳
        fmt.Println(t5.Unix());
        //返回纳秒时间戳
        fmt.Println(t5.UnixNano());
     
        //时间的比较与计算
        t6 := time.Now();
        //是否零时时间
        fmt.Println(t6.IsZero());
        //t6时间在t5时间之后,返回真
        fmt.Println(t6.After(t5));
        //t5时间在t6时间之前,返回真
        fmt.Println(t5.Before(t6));
        //时间是否相同
        fmt.Println(t6.Equal(t6));
        //返回t6加上纳秒的时间
        fmt.Println(t6.Add(10000));
        //返回两个时间之差的纳秒数
        fmt.Println(t6.Sub(t5));
        //返回t6加1年,1月,1天的时间
        fmt.Println(t6.AddDate(1, 1, 1));
     
        //时间的序列化
        t7 := time.Now();
        //序列化二进制
        bin, _ := t7.MarshalBinary();
        //反序列化二进制
        t7.UnmarshalBinary(bin)
        fmt.Println(t7);
        //序列化json
        json, _ := t7.MarshalJSON();
        fmt.Println(string(json));
        //反序列化json
        t7.UnmarshalJSON(json);
        fmt.Println(t7);
        //序列化文本
        txt, _ := t7.MarshalText();
        fmt.Println(string(txt));
        //反序列化文本
        t7.UnmarshalText(txt);
        fmt.Println(t7);
        //gob编码
        gob, _ := t7.GobEncode();
        t7.GobDecode(gob);
        fmt.Println(t7);
     
        //时间段time.Duration
        dur := time.Duration(6666666600000);
        //返回字符串表示
        fmt.Println(dur.String());
        //返回小时表示
        fmt.Println(dur.Hours());
        //返回分钟表示
        fmt.Println(dur.Minutes());
        //返回秒表示
        fmt.Println(dur.Seconds());
        //返回纳秒表示
        fmt.Println(dur.Nanoseconds());
     
        //时区time.Location
        //返回时区名
        fmt.Println(time.Local.String());
     
        //通过地点名和时间偏移量返回时区
        fmt.Println(time.FixedZone("Shanghai", 800));
     
        //通过给定时区名称,返回时区
        loc, _ := time.LoadLocation("Asia/Shanghai");
        fmt.Println(loc);
     
        //阻塞当前进程3秒
        time.Sleep(time.Second * 3);
     
        //定时器time.Timer
        //创建一个1秒后触发定时器
        timer1 := time.NewTimer(time.Second * 1);
        <-timer1.C;
        fmt.Println("timer1 end");
     
        //1秒后运行函数
        time.AfterFunc(time.Second * 1, func() {
            fmt.Println("wait 1 second");
        });
        time.Sleep(time.Second * 3);
     
        //打点器time.Ticker
        //创建一个打点器,在固定1秒内重复执行
        ticker := time.NewTicker(time.Second);
        num := 1;
        for {
            if num > 5 {
                //大于5次关闭打点器
                ticker.Stop();
                break;
            }
            //否则从打点器中获取chan
            select {
            case <-ticker.C:
                num++;
                fmt.Println("1 second...");
            }
        }
    }
    } else if condition2 {
    } else if condition3 {

    } else {
    }

    for循环条件没有小括号

    for i := 0; i < 10; i++ {
    }

    死循环

    for true {
    }
    可以简写为:
    for {
    }

    range

    for i, v := range str {
    }
    package main
    
    import (
        "fmt"
    )
    
    func ran(str string) {
        for i, v := range str {
            fmt.Printf("index[%d] val[%c] len[%d]
    ", i, v, len([]byte(string(v))))
        }
    }
    
    func main() {
        ran("Love, 索宁")
    }
  • 相关阅读:
    [VC++]利用VS2005进行dump文件调试
    Release和Debug模式下成员变量初始化问题
    JDBC与C++的DB访问性能
    Log4J与LogBack的性能比较
    WinRar命令行参数
    玩弄C++:回调一个类成员函数
    如何将一个模板类A作为模板类B的模板参数
    HibernateException: Unable to instantiate default tuplizer [org.hibernate.tuple.entity.PojoEntityTup
    HibernateException: Unable to instantiate default tuplizer [org.hibernate.tuple.entity.PojoEntityTup
    使用jQuery发送POST,Ajax请求返回JSON格式数据
  • 原文地址:https://www.cnblogs.com/klb561/p/10740895.html
Copyright © 2020-2023  润新知