04-Go语言常量和变量

Go数据类型

  • C语言的数据类型


    image
  • GO语言数据类型


    image
  • GO数据类型占用的内存空间


    image
package main

import (
    "fmt"
    "unsafe"
)

func main() {
    // 有符号的整型
    fmt.Println("int size = ", unsafe.Sizeof(int(0)))  // 8
    fmt.Println("int8 size = ", unsafe.Sizeof(int8(0)))  // 1
    fmt.Println("int16 size = ", unsafe.Sizeof(int16(0)))  // 2
    fmt.Println("int32 size = ", unsafe.Sizeof(int32(0)))  // 4
    fmt.Println("int64 size = ", unsafe.Sizeof(int64(0)))   // 8
    // 结论: int会根据系统自动调整,如果系统是64的,那么int就会变成int64,
    // 如果系统是32的, 那么int 就会变成32位



    // 无符号的整型
    fmt.Println("uint size = ", unsafe.Sizeof(uint(0)))   //  8
    fmt.Println("uint8 size = ", unsafe.Sizeof(uint8(0)))   // 1
    fmt.Println("uint16 size = ", unsafe.Sizeof(uint16(0)))   // 2
    fmt.Println("uint32 size = ", unsafe.Sizeof(uint32(0)))   // 4
    fmt.Println("uint64 size = ", unsafe.Sizeof(uint64(0)))   // 8

    // 字符类型
    fmt.Println("byte size = ", unsafe.Sizeof(byte(0)))   // 1
    fmt.Println("rune size = ", unsafe.Sizeof(rune(0)))   // 4
    fmt.Println("中文字符 = ", unsafe.Sizeof('好'))   // 4

    // 浮点类型
    fmt.Println("float32 size = ", unsafe.Sizeof(float32(0)))   // 4
    fmt.Println("float64 size = ", unsafe.Sizeof(float64(0)))   // 8

    // 布尔类型
    fmt.Println("true size = ", unsafe.Sizeof(true))   //  1
    fmt.Println("false size = ", unsafe.Sizeof(false))   // 1


}

  • 注意点:
    • 在GO语言中我们可以通过Sizeof来计算数据类型占用的内存大小
    • 使用Sizeof函数必须导入unsafe这个包
    • 通过unsafe.Sizeof()来调用这个方法
    • Sizeof的首字母必须大写
    • Go语言中int类型,会根据系统自动调整占用内存的字节数
    • 如果是64位系统, 那么int就是int64, 占用 8个字节
    • 如果是32位系统, 那么int就是int32, 占用 4个字节

GO语言变量

  • 变量: 可以改变的数据称为变量
  • 定义变量: 就是告诉系统需要分配多大的内存空间来存储数据
  • 格式:
    • 1.var 变量名称 数据类型
    • 2.var 变量名称 数据类型 = 值
    • 3.var 变量名称 = 值
    • 4.变量名称 := 值
    package main
    
    import (
        "fmt"
    )
    
    func main() {
        // 先定义后初始化
        var num int
        num = 666
        fmt.Printf("num = %d\n", num)   // 666
    
        // 定义的同时初始化
        var num1 int =  123
        fmt.Println("num1 = ", num1)
    
        // 定义的同时初始化, 并省略数据类型
        var num2 = 234
        fmt.Println("num2 = ", num2)
        // fmt.Println("int sizeof = ", unsafe.Sizeof(num2))
    
        // 定义的同时初始化, 并省略数据类型和var
        // := 做了两件事
        //  1. 先定义一个变量
        //  2. 给定义的变量赋值
         num3 := 100
         fmt.Println("num3 = ", num3)
    
         // num4 int:= 23
         // := 定义变量的同时不能添加数据类型
    
         var num5 := 555
         // := 定义变量的同时不能添加 var 
        fmt.Println("num4 = ", num5)
    }
    
    

连续定义多个变量

  • 格式:
    • 1.可以通过逗号来定义多个变量
    // 先定义变后初始化
    var a , b , c int
    a = 1
    b = 2
    c = 3
    
    // 定义变量的同时初始化
    var a , b, c int = 1, 2, 3
    
    
    • 2.可以使用变量组来同时定义多个变量
    // 先定义变量后初始化
    var(
        a int 
        b int
        c int
    )
    a = 1
    b = 2
    c = 3
    
    
    // 定义变量同时初始化
    var (
        a int = 1
        b int = 2
        c int = 3
    )    
    
    // 注意点: 变量组中不能使用 := 来定义变量
    // var (
    //    a := 1
    //    b := 2
    // )
    

定义变量的注意点:

  • 定义变量的时候, 如果省略数据类型那么系统会自动根据数值推断出变量的数据类型
  • 使用 := 定义变量的时候, 那么不能写var 也不能写数据类型
  • 使用 := 定义变量的时候, 只能定义局部变量不能定义全局变量
  • 使用 := 定义变量的时候, 变量组中不能使用 := 的格式
  • 使用 := 定义多个变量的时候, 变量如果已经定义过了那么将退化成赋值操作
// 定义一个变量
var num int = 234
// 对于num已经定义过了, 那么将退化成赋值操作
num , value := 666, 777
fmt.Println("num = ", num, "value = ", value)
  • 重复定义变量编译报错
    package main

    import "fmt"
    
    func main() {
    
        num := 234
        num := 666
        fmt.Println("num = ", num)
    }
    

全局变量和局部变量

  • 局部变量:
    • 含义: 定义在函数内部的变量,以及函数的形参就称为局部变量
    • 作用域: 从定义的哪一行开始到遇到}和return,到代码块结束就释放
    • 生命周期: 从程序运行到哪一行才分配存储空间, 离开作用域就释放空间
  • 全局变量:
    • 含义: 定义在函数外部的变量称为全局变量
    • 作用域: 从定义哪一行开始到文件的结尾
    • 生命周期: 程序一启动就分配存储空间, 知道程序结束
  • 注意点:
    • GO语言中不管是定义局部变量还是全局变量都不能出现同名的变量
    • GO语言中,如果定义一个局部变量, 但是没用使用这个变量, 编译报错
    • GO语言中,如果定义一个全局变量, 但是没用使用这个变量, 编译不会报错

数值类型和字符串类型之间的转换

  • GO语言中只有显示转换, 没有隐式转换
  • 数据类型一般用于除了字符串和布尔类型以外的其他基本类型的转换
package main

func main() {
    // go语言中只有显示转换没有隐式转换
    // 格式:数据类型(被转换的数据)

     num int = 3.14  // 报错
    fmt.Println("num = ", num)

     不能对一个常量进行类型的强行转换
    var num1 int = int(3.14)
    fmt.Println("num1 = ", num1)

    // 正确做法
    // go语言中数据类型必须一模一样才能直接赋值
    var num3 float64 = 3.14
    var value int = int(num3)
    fmt.Println("value = ", value)  // 3

    // 特殊情况
    var ch byte = 'a'
    var num4 uint8 = ch    // type byte = uint8  本质
    fmt.Println("num4 = ", num4)  // 97

    var ch1 rune = '好'
    var num5 int32 = ch1
    fmt.Println("num5 = ", num5)  // 22909 UTF -8

    // bool 类型不能转换为整型
    //var flag bool = false
    //var num6 int = flag
    //fmt.Println("num6 = ", num6)

    // 整型也可以转换成字符类型, 但是不推荐使用
    //var num7 int = 97
    //var str string = string(num7)
    //fmt.Println("str = ", str)   // a

}

  • 基本数据类型转换成字符串类型
    • 方法一: strconv.FormatXxx()
    • 方法二: strconv.Itoa()
package main

import (
    "fmt"
    "strconv"
    "unsafe"
)

func main() {
    // 基本数据类型转换为字符串类型
    // 1. strconv.FormatXxx()
    // 2. strconv.Itoa()

    // strconv.FormatInt()
    // func FormatInt(i int64, base int) string
    // 第一个参数: 需要转换的整数, 必须是int64类型的
    // 第二个参数: 转换为多少进制的字符串
    var num1 int = 9
    var str1 string = strconv.FormatInt(int64(num1), 10)
    var str2 string = strconv.FormatInt(int64(num1), 2)
    fmt.Println("str1 = ", str1) // 9
    fmt.Println("str2 = ", str2)// 1001
    var str3 string = strconv.FormatInt(int64(3), 10)
    fmt.Println("str3 = ", str3) // 3

    // strconv.FormatFloat()
    // func FormatFloat(f float64, fmt byte, prec, bitSize int) string
    // 第一个参数: 需要转换的小数
    // 第二个参数: 按照什么格式转换  'f' 小数格式,  'e' 指数格式
    // 第三个参数: 保留多少位小数, 传入 -1按照原始类型的精度保留
    // 第四个参数: 原始类型的标志  float32 --> 32  float64 --> 64
    var  num2 = 3.14
    var  str4 string = strconv.FormatFloat(float64(num2), 'f', -1,32)
    fmt.Println("str4 = ", str4)  // 3.14
    fmt.Println("sizeof num2 = ", unsafe.Sizeof(num2))  // 8

    // strconv.FormatBool
    // func FormatBool(b bool) string
    var flag bool = false
    var str5 string = strconv.FormatBool(flag)
    fmt.Println("str5 = ", str5) // false

    // strconv.Itoa()
    // func Itoa(i int) string
    var num3 int = 233
    //var  num3 int64 = 332
    var str6 string = strconv.Itoa(int(num3))
    fmt.Println("str6 = ", str6)  // 233




}

  • 字符类型转换为基本数据类型
    • 方法一: strconv.ParseXxx()
    • 方法二: strconv.Atoi()
package main

import (
    "fmt"
    "strconv"
)

func main() {
    // Go语言中字符串类型转换为基本数据类型
    // strconv.ParseXxx()
    // strconv.Atoi()

    //  strconv.ParseInt()
    // func ParseInt(s string, base int, bitSize int) (i int64, err error)
    // 第一个参数: 需要转换的字符串
    // 第二个参数: 被转化的字符串保存的整数是多少进制的(原来的字符是多少进制的)
    // 第三个参数: 期望转换为多少位的整数
    // 返回值有两个
    // 第一个返回值: 转后之后的数值, 是int64 类型
    // 第二个返回值: 如果转换成功返回nil, 如果转换失败就不是nil
    var str1 = "1010"
    // num, err := strconv.ParseInt(str1, 10, 8)
    num, err := strconv.ParseInt(str1, 2, 8)
    if err != nil{
        fmt.Println("转换失败")
    }else{
        fmt.Println("num = ", num)  // 9
        fmt.Printf("%T ", num) // int64
    }
    // strconv.ParseFloat()
    //func ParseFloat(s string, bitSize int) (float64, error)
    // 第一个参数: 需要转换的字符串
    // 第二个参数: 要将字符串中的小数转换为单精度还是双精度, 单精度传入32, 双精度传入64
    // 返回两个返回值
    // 第一个返回值: 转换成功之后的小数, float64类型
    // 第二个返回值: 转换成功返回 nil, 转换失败不为 nil
    str2 := "3.123456789"
    num1, err := strconv.ParseFloat(str2, 32)
    if err != nil{
        fmt.Println("转换失败")
    }else{
        fmt.Println("num1 = ", num1)
        fmt.Printf("%T", num1)  // float64
    }

    // strconv.ParseBool()
    //func ParseBool(str string) (bool, error)
    var str3 string = "false"
    flag, err := strconv.ParseBool(str3)
    fmt.Println("flag = ", flag) // false
    fmt.Printf("%T\n", flag)  // bool

    // strconv.Atoi()
    // func Atoi(s string) (int, error)
    // 传入一个字符串
    // 返回两个值, 第一个是转换成功后的数, 第二个返回值是 : 转换成功返回nil,
    var str4 string = "99"
    num2, err :=  strconv.Atoi(str4)
    if err != nil{
        fmt.Println("转换失败")
    }else{
        fmt.Println("num2 = ", num2)
    }


}


GO语言常量

  • GO语言常量分为整型常量, 实型常量, 字符常量, 字符串常量, 自定义常量
  • 自定义常量
    • 格式: const 常量名称 数据类型 = 值 或者 const 常量名称 = 值
package main

import "fmt"

func main() {
    // 格式: const 变量名称 数据类型 = 值
    const   num1 int = 222
    // num1 = 111   // 常量不能赋值, 否则报错
    fmt.Println("num1 = ", num1)

    // 给多个变量赋值
    // 格式: const 变量名1 , 变量名2 数据类型 = 值1, 值2
    const num2 , num3 int = 10, 20
    fmt.Println("num2 = ", num2, "num3 = ", num3)

    // 使用变量组给常量赋值
    const (
        num4 int = 33
        num5 int = 44
        num6 int = 55
    )
    fmt.Println(num4, num5, num6)

    // 变量组的定义多个变量的注意点
    // 如果常量没有赋值, 那么默认值就是上一行的取值
    //const  (
    //  a = 10
    //  b = 20
    //  c = 30
    //)
    // fmt.Println(a, b, c) // 10 20 30

    //const  (
    //  a = 10
    //  b = 20
    //  c
    //)
    // fmt.Println(a, b, c) // 10 20 20

    const(
        a , b = 10, 20
        c, d
    )
    fmt.Println(a, b) // 10, 20
    fmt.Println(c, d) // 10, 20




}

  • 注意点:
    • 不能给常量赋值, 会报错
    • 在常量组中, 如果常量没有赋值, 那么值为上一行的值
  • 枚举常量
  • 格式
const (
    枚举元素1 = 值
    枚举元素2 = 值
)
package main

import "fmt"

func main() {
    // 枚举类型的本质就是整型常量
    // Go语言和C语言一样都是从0开始递增, 每行递增1
    /*const(
        male =  iota
        female = iota
        yy = iota
    )*/
    // 等同于下面的写法
    const(
        male =  iota
        female
        yy
    )
    // 只要有一行出现了iota, 那么后续会自动递增

    fmt.Println("male = ", male)  // 0
    fmt.Println("female = ", female)  // 1
    fmt.Println("yy = ", yy)    //  2

    // 如果常量组中被打断了, 那么就不会继续递增了,
    // 而是会按照常量的的方式处理, 不赋值就会等于上一行的值
    const (
        a = iota
        b = 888
        c
    )

    fmt.Println("a = ", a)  //  0
    fmt.Println("b = ", b)   // 888
    fmt.Println("c = ", c)   // 888



    // 如果常量组中的iota被打断了, 但是后续又恢复, 那么前面有多少行,就会递增多少
    const (
        num1 = iota
        num2 = 111
        num3 = iota
    )
    fmt.Println("num1 = ",num1)   // 0
    fmt.Println("num2 = ",num2)   // 111
    fmt.Println("num3 = ",num3)   // 2




}

  • 注意点:
    • Go语言和C语言的枚举一样,利用iota标识符从0开始递增,每行增加1
    • 在常量组中, iota只要上一行出现了, 那么下一行不赋值也会递增
    • 但是如果常量组中, 被常量打断了, 那么就会等于上一行的值
    • 常量组如果被打断,后续又恢复,那么前面有多少行就会递增多少
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,772评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,458评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,610评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,640评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,657评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,590评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,962评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,631评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,870评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,611评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,704评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,386评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,969评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,944评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,179评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,742评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,440评论 2 342

推荐阅读更多精彩内容