05-Go语言常量和变量-指趣学院

Go语言数据类型

  • Go语言本质是用C语言编写的一套高级开发语言, 所以Go语言中的数据类型大部分都是由C语言演变而来的

  • C语言数据类型


  • Go语言数据类型



  • C语言各数据类型占用内存空间
类型 32位编译器 64位编译器
char 1 1
int 4 4
float 4 4
double 8 8
short 2 2
long 4 8
long long 8 8
void* 4 8
  • Go语言各数据类型占用内存空间
类型 32位编译器 64位编译器 本质
int8/uint8 1 1 signed char/unsigned char
int16/uint16 2 2 signed short/unsigned short
int32/uint32 4 4 signed int/unsigned int
int64/uint64 8 8 signed long long int/unsigned long long int
byte 1 1 uint8/unsigned char
rune 4 4 int32/signed int
int 4 8 根据机器位数决定长度
uintptr 4 8 根据机器位数决定长度 uint32/uint64
float32 4 4 float
float64 8 8 double
true 1 1 char类型的整型
false 1 1 char类型的整型
  • 和C语言一样,Go语言也提供了Sizeof计算变量的内存空间
    • 1.导入import "unsafe"包
    • 2.通过unsafe.Sizeof()计算变量内存空间
package main

import (
    "fmt"
    "unsafe"
)

func main() {
    fmt.Println("int size = ", unsafe.Sizeof(int(0)))
    fmt.Println("int8 size = ", unsafe.Sizeof(int8(0)))
    fmt.Println("int16 size = ", unsafe.Sizeof(int16(0)))
    fmt.Println("int32 size = ", unsafe.Sizeof(int32(0)))
    fmt.Println("int64 size = ", unsafe.Sizeof(int64(0)))
    fmt.Println("uint size = ", unsafe.Sizeof(uint(0)))
    fmt.Println("uint8 size = ", unsafe.Sizeof(uint8(0)))
    fmt.Println("uint16 size = ", unsafe.Sizeof(uint16(0)))
    fmt.Println("uint32 size = ", unsafe.Sizeof(uint32(0)))
    fmt.Println("uint64 size = ", unsafe.Sizeof(uint64(0)))
    fmt.Println("uintptr size = ", unsafe.Sizeof(uintptr(0)))
    fmt.Println("byte size = ", unsafe.Sizeof(byte(0)))
    fmt.Println("rune size = ", unsafe.Sizeof(rune(0)))
    fmt.Println("float32 size = ", unsafe.Sizeof(float32(0)))
    fmt.Println("float64 size = ", unsafe.Sizeof(float64(0)))
    fmt.Println("true size = ", unsafe.Sizeof(true))
    fmt.Println("false size = ", unsafe.Sizeof(false))

}

  • Go语言基本数据类型内部实现
    • golang官方网站下载go1.4版本源代码
      • 越老版本的代码越纯粹,越适合新手学习
      • 随着代码的更新迭代会逐步变得非常复杂, 所以此处建议下载1.4版本
    • 解压后打开路径: go\src\runtime\runtime.h
    • 得到如下实现代码
// 第8行到35行
typedef signed char     int8;
typedef unsigned char       uint8;
typedef signed short        int16;
typedef unsigned short      uint16;
typedef signed int      int32;
typedef unsigned int        uint32;
typedef signed long long int    int64;
typedef unsigned long long int  uint64;
typedef float           float32;
typedef double          float64;

#ifdef _64BIT
typedef uint64      uintptr;
typedef int64       intptr;
typedef int64       intgo; // Go's int
typedef uint64      uintgo; // Go's uint
#else
typedef uint32      uintptr;
typedef int32       intptr;
typedef int32       intgo; // Go's int
typedef uint32      uintgo; // Go's uint
#endif

#ifdef _64BITREG
typedef uint64      uintreg;
#else
typedef uint32      uintreg;
#endif

// 第153行到157行
enum
{
    true    = 1,
    false   = 0,
};

install B 时刻:
Go本质就是用C语言编写的一门高级编程语言
所以江哥前面教你C语言就是为了今天能让你看懂Go的实现代码,做到知其然知其所以然
注意点: 企业开发中一般使用int, 因为int会根据你当前的操作系统自动转换为int32和int64


Go语言变量

  • Go语言中变量的概念和C语言中也一样, 所以我们直接来看下如何定义和使用变量即可
  • C语言中定义变量的格式
数据类型 变量名称;
数据类型 变量名称1, 变量名称2;
#include <stdio.h>

int main(int argc, const char * argv[])
{
    int num1; // 先定义
    num1 = 10; // 后初始化
    printf("num1 = %d\n", num1);

    int num2 = 20; // 定义的同时初始化
    printf("num2 = %d\n", num2);

    // 注意: 同时定义多个变量,不支持定义时初始化, 只能先定义后初始化
    int num3, num4; //同时定义多个变量
    num3 = 30;
    num4 = 40;
    printf("num3 = %d\n", num3);
    printf("num4 = %d\n", num4);

    return 0;
}
  • Go语言中定义变量有三种格式
// 标准格式
var 变量名称 数据类型 = 值;
// 自动推到类型格式
var 变量名称 = 值;
// 简短格式(golang官方推荐格式)
变量名称 := 值;
package main
import "fmt"
func main() {
    var num1 int // 先定义
    num1 = 10 // 后赋值
    fmt.Println("num1 = ", num1)

    var num2 int = 20 // 定义的同时赋值
    fmt.Println("num2 = ", num2)

    var num3  = 30 // 定义的同时赋值, 并省略数据类型
    fmt.Println("num3 = ", num3)
    
    num4  := 40 // 定义的同时赋值, 并省略关键字和数据类型
    /*
    num4  := 40 等价于
    var num4 int
    num4 = 40
    */
    fmt.Println("num4 = ", num4)
}
  • 和C语言一样,除了可以定义单个变量以外,还支持一次性定义多个变量
    • 方式一, 连续定义
     package main
     import "fmt"
     func main() {
         var num1, num2 int // 先定义
         num1 = 10   // 后赋值
         num2 = 20
         fmt.Println("num1 = ", num1)
         fmt.Println("num2 = ", num2)
     
         var num3, num4 int = 30, 40 // 定义的同时赋值
         fmt.Println("num3 = ", num3)
         fmt.Println("num4 = ", num4)
     
         var num5, num6 = 50, 60 // 定义的同时赋值, 并省略数据类型
         fmt.Println("num5 = ", num5)
         fmt.Println("num6 = ", num6)
     
         num7, num8 := 70, 80 // 定义的同时赋值, 并省略关键字和数据类型
         fmt.Println("num7 = ", num7)
         fmt.Println("num8 = ", num8)
     }
    
    • 方式二, 变量组
      package main
      import "fmt"
      func main() {
          var( // 先定义
              num1 int
              num2 float32
          )
          num1 = 10 // 后赋值
          num2 = 3.14
          fmt.Println("num1 = ", num1)
          fmt.Println("num2 = ", num2)
    
          var( // 定义的同时赋值
              num3 int = 30
              num4 float32 = 6.66
          )
          fmt.Println("num3 = ", num3)
          fmt.Println("num4 = ", num4)
    
          var( // 定义的同时赋值, 并省略数据类型
              num5 = 50
              num6 = 7.77
          )
          fmt.Println("num5 = ", num5)
          fmt.Println("num6 = ", num6)
    
          var( // 一行定义多个
              num7, num8 = 70, 80
              num9, num10 = 9.99, 100
          )
          fmt.Println("num7 = ", num7)
          fmt.Println("num8 = ", num8)
          fmt.Println("num9 = ", num9)
          fmt.Println("num10 = ", num10)
      }
    

Go语言变量定义注意点

  • 简短模式的含义是定义的同时初始化
package main
import "fmt"
func main() {
    num := 10
    num := 20 // 编译报错, 重复定义
    fmt.Println("num = ", num)
}
  • 一定不要把:=当做赋值运算符来使用
package main
import "fmt"
var num = 10 // 定义一个全局变量
func main() {
    num := 20 // 定义一个局部变量
    fmt.Println("num = ", num)
        test()
}
func test() {
    fmt.Println("num = ", num) // 还是输出10
}

  • :=只能用于定义局部变量,不能用于定义全局变量
package main
import "fmt"
num := 10 // 编译报错
func main() {
    fmt.Println("num = ", num)
}
  • 使用:=定义变量时,不能指定var关键字和数据类型
package main
import "fmt"
func main() {
    //var num int := 10 // 编译报错
    //var num := 10 // 编译报错
    num int := 10 // 编译报错
    fmt.Println("num = ", num)
    fmt.Println("num = ", num)
}
  • 变量组中不能够使用:=
package main
import "fmt"
func main() {
    var(
        num := 10 // 编译报错
    )
    fmt.Println("num = ", num)
}
  • 通过:=同时定义多个变量, 必须给所有变量初始化
package main
import "fmt"
func main() {
    //num1, num2 := 666, 888 // 正确
    num1, num2 := 666 // 报错
    fmt.Printf("%d, %d\n", num1, num2)
}
  • 通过:=同时定义多个变量, 只要任意一个变量没有定义过,都会做退化赋值操作
package main
import "fmt"
func main() {
    // 定义一个变量num1
    num1 := 10
    // 同时定义两个变量num1和num2, 由于num2从来没有定义过,
    // 所以对于num1来说:=退化为赋值运算符, 而对于num2来说:=仍然是定义+赋值
    num1, num2 := 20, 30
    fmt.Println("num1 = ", num1)
    fmt.Println("num2 = ", num2)
}
package main
import "fmt"
func main() {
    num1 := 10
    num2 := 20
    // 报错, 因为num1,和num2都已经被定义过
    // 至少要有任意一个变量没有被定义过,才会退化赋值
    num1, num2 := 30, 40
    fmt.Println("num1 = ", num1)
    fmt.Println("num2 = ", num2)
}
  • 定义的局部变量或者导入的包没有被使用, 那么编译器会报错,无法编译运行,但是定义的全局变量没有被使用,编译器不会报错, 可以编译运行

局部变量和全局变量

  • 和C语言一样,按照变量的作用域,我们可以把变量划分为局部变量和全局变量

  • Go语言中局部变量的概念以及全局变量的概念和C语言一模一样

  • 局部变量:

    • 定义在函数内部的变量以及函数的形参称为局部变量
    • 作用域:从定义哪一行开始直到与其所在的代码块结束
    • 生命周期:从程序运行到定义哪一行开始分配存储空间到程序离开该变量所在的作用域
  • 全局变量:

    • 定义在函数外面的变量称为全局变量
    • 作用域范围:从定义哪行开始直到文件结尾
    • 生命周期:程序一启动就会分配存储空间,直到程序结束
  • 和C语言不同的是, C语言中可以定义相同名称的全局变量, 而Go语言中无论全局变量还是局部变量, 只要作用域相同都不能出现同名的变量

package main
import "fmt"
//var num1 int
//var num1 int // 报错, 重复定义
var num3 int
func main() {
    //var num2
    //var num2 // 报错, 重复定义
    
    var num3 int // 不报错, 因为作用域不同
    fmt.Println("num3 = ", num3)
}

  • C语言中全局变量没有赋值,那么默认初始值为0, 局部变量没有赋值,那么默认初始值是随机值
  • Go语言中无论是全局变量还是局部变量,只要定义了一个变量都有默认的0值
    • int/int8/int16/int32/int64/uint/uint8/uint16/uint32/uint64/byte/rune/uintptr的默认值是0
      +float32/float64的默认值是0.0
    • bool的默认值是false
    • string的默认值是""
    • pointer/function/interface/slice/channel/map/error的默认值是nil
    • 其它复合类型array/struct默认值是内部数据类型的默认值
package main
import "fmt"
func main() {
    var intV int // 整型变量
    var floatV float32 // 实型变量
    var boolV bool // 布尔型变量
    var stringV string // 字符串变量
    var pointerV *int // 指针变量
    var funcV func(int, int)int // function变量
    var interfaceV interface{} // 接口变量
    var sliceV []int // 切片变量
    var channelV chan int // channel变量
    var mapV map[string]string // map变量
    var errorV error // error变量

    fmt.Println("int = ", intV) // 0
    fmt.Println("float = ", floatV) // 0
    fmt.Println("bool = ", boolV) // false
    fmt.Println("string = ", stringV) // ""
    fmt.Println("pointer = ", pointerV) // nil
    fmt.Println("func = ", funcV) // nil
    fmt.Println("interface = ", interfaceV) // nil
    fmt.Println("slice = ", sliceV) // []
    fmt.Println("slice = ", sliceV == nil) // true
    fmt.Println("channel = ", channelV) // nil
    fmt.Println("map = ", mapV) // map[]
    fmt.Println("map = ", mapV == nil) // true
    fmt.Println("error = ", errorV) // nil

    var arraryV [3]int // 数组变量
    type Person struct{
        name string
        age int
    }
    var structV Person // 结构体变量
    fmt.Println("arrary = ", arraryV) // [0, 0, 0]
    fmt.Println("struct = ", structV) // {"" 0}
}

数据类型转换

  • C语言中数据可以隐式转换或显示转换, 但是Go语言中数据只能显示转换
  • C语言隐式转换
#include <stdio.h>
int main(){
  // 隐式转换:自动将实型10.6转换为整型后保存
   int a = 10.6;
 // 自动类型提升: 运算时会自动将小类型转换为大类型后运算
  double b = 1.0 / 2; // 等价于1.0 / 2.0
}
  • C语言显示转换(强制转换)
#include <stdio.h>
int main(){
  // 显示转换:强制将实型10.6转换为整型后保存
  int a = (int)10.5;
}
  • Go语言数值类型之间转换
    • 格式: 数据类型(需要转换的数据)
    • 注意点: 和C语言一样数据可以从大类型转换为小类型, 也可以从小类型转换为大类型. 但是大类型转换为小类型可能会丢失精度
      package main
      import "fmt"
      func main() {
          var num0 int = 10
          var num1 int8 = 20
          var num2 int16
          //num2 = num0 // 编译报错, 不同长度的int之间也需要显示转换
          //num2 = num1 // 编译报错, 不同长度的int之间也需要显示转换
          num2 = int16(num0)
          num2 = int16(num1)
          fmt.Println(num2)
      
          var num3 float32 = 3.14
          var num4 float64
          //num4 = num3 // 编译报错, 不同长度的float之间也需要显示转换
          num4 = float64(num3)
          fmt.Println(num4)
      
          var num5 byte = 11
          var num6 uint8 // 这里不是隐式转换, 不报错的原因是byte的本质就是uint8
          num6 = num5
          fmt.Println(num6)
      
          var num7 rune = 11
          var num8 int32
          num8 = num7 // 这里不是隐式转换, 不报错的原因是byte的本质就是int32
          fmt.Println(num8)
      }
    


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

  • Go语言中不能通过 数据类型(变量)的格式将数值类型转换为字符串, 也不能通过 数据类型(变量)的格式将字符串转换为数值类型
    package main
    import "fmt"
    func main() {
        var num1 int32 = 65
        // 可以将整型强制转换, 但是会按照ASCII码表来转换
        // 但是不推荐这样使用
        var str1 string = string(num1)
        fmt.Println(str1)

        var num2 float32 = 3.14
        // 不能将其它基本类型强制转换为字符串类型
        var str2 string = string(num2)
        fmt.Println(str2)

        var str3 string = "97"
        // 不能强制转换, cannot convert str2 (type string) to type int
        var num3  int = int(str3)
        fmt.Println(num3)
    }
  • 数值类型转字符串类型strconv..FormatXxx()
  package main
  import "fmt"
  func main() {
      var num1 int32 = 10
      // 第一个参数: 需要被转换的整型,必须是int64类型
      // 第二个参数: 转换为几进制,  必须在2到36之间
      // 将32位十进制整型变量10转换为字符串,并继续保留10进制格式
      str1 := strconv.FormatInt(int64(num1), 10)
      fmt.Println(str1) // 10
      // 将32位十进制整型变量10转换为字符串,并转换为2进制格式
      str2 := strconv.FormatInt(int64(num1), 2)
      fmt.Println(str2) // 1010

      var num5 float64 = 3.1234567890123456789
      // 第一个参数: 需要转换的实型, 必须是float64类型
      // 第二个参数: 转换为什么格式,f小数格式, e指数格式
      // 第三个参数: 转换之后保留多少位小数, 传入-1按照指定类型有效位保留
      // 第四个参数: 被转换数据的实际位数,float32就传32, float64就传64
      // 将float64位实型,按照小数格式并保留默认有效位转换为字符串
      str3 := strconv.FormatFloat(num5, 'f', -1, 64)
      fmt.Println(str3) // 3.1234567
      str4 := strconv.FormatFloat(num5, 'f', -1, 64)
      fmt.Println(str4) // 3.1234567890123457
      // 将float64位实型,按照小数格式并保留2位有效位转换为字符串
      str5 := strconv.FormatFloat(num5, 'f', 2, 64)
      fmt.Println(str5) // 3.12
      // 将float64位实型,按照指数格式并保留2位有效位转换为字符串
      str6 := strconv.FormatFloat(num5, 'e', 2, 64)
      fmt.Println(str6) // 3.12

      var num6 bool = true
      str7 := strconv.FormatBool(num6)
      fmt.Println(str7) // true
  }
  • 字符串类型转数值类型strconv.ParseXxx()
  package main
  import "fmt"
  func main() {
      var str1 string = "125"
      // 第一个参数: 需要转换的数据
      // 第二个参数: 转换为几进制
      // 第三个参数: 转换为多少位整型
      // 注意点: ParseInt函数会返回两个值, 一个是转换后的结果, 一个是错误
      // 如果被转换的数据转换之后没有超出指定的范围或者不能被转换时,
      // 那么错误为nil, 否则错误不为nil
      // 将字符串"125"转换为10进制的int8
      num1, err := strconv.ParseInt(str1, 10, 8)
      if err != nil {
          fmt.Println(err)
      }
      fmt.Println(num1)

      var str2 string = "150"
      // 将字符串"150"转换为10进制的int8
      // 由于int8的取值范围是-128~127, 所以转换之后超出了指定的范围, error不为nil
      num2, err := strconv.ParseInt(str2, 10, 8)
      if err != nil {
          fmt.Println(err)
      }
      fmt.Println(num2)

      var str3 string = "3.1234567890123456789"
      // 第一个参数: 需要转换的数据
      // 第二个参数: 转换为多少位小数, 32 or 64
      // ParseFloat同样有两个返回值, 如果能够正常转换则错误为nil, 否则不为nil
      num3, err := strconv.ParseFloat(str3, 32)
      if err != nil {
          // 例如: 把字符串"3.14abc"转换为小数就会报错, 因为"3.14abc"不是一个小数
          fmt.Println(err)
      }
      fmt.Println(num3)

      var str4 string = "true"
      // 第一个参数: 需要转换的数据
      // ParseBool同样有两个返回值, 如果能够正常转换则错误为nil, 否则不为nil
      num4, _ := strconv.ParseBool(str4)
      fmt.Println(num4)
  }
  • 字符串类型转换为数值类型时,如果不能转换除了返回error以外,还会返回对应类型的默认值
    package main
    import "fmt"
    func main() {
        var str1 string = "abc"
        num1, _ := strconv.ParseInt(str1, 10, 32)
        fmt.Println(num1) // 0

        num2, _ := strconv.ParseFloat(str1, 32)
        fmt.Println(num2) // 0

        num3, _ := strconv.ParseBool(str1)
        fmt.Println(num3) // false
    }
  • 看完上面的代码有没有种想打人的感觉? 如果有那么请继续往下看
  • 字符串类型和整型快速转换
   package main
   import "fmt"
   func main() {
       var num1 int32 = 110
       // 快速将整型转换为字符串类型
       // 注意:Itoa方法只能接受int类型
       var str1 string = strconv.Itoa(int(num1))
       fmt.Println(str1)

       var str2 string = "666"
       // 快速将字符串类型转换为整型
       // 注意: Atoi方法返回两个值, 一个值是int,一个值是error
       // 如果字符串能被转换为int,那么error为nil, 否则不为nil
       num2, err := strconv.Atoi(str2)
       if err != nil{
           fmt.Println(err)
       }
       fmt.Println(num2)
   }
  • 数值类型转字符串类型其它方式
  package main
  import "fmt"
  func main() {
      var num1 int32 = 110
      // Sprintf函数和Printf函数很像, 只不过不是输出而将格式化的字符串返回给我们
      var str1 string = fmt.Sprintf("%d", num1)
      fmt.Println(str1)

      var num2 float32 = 3.14
      var str2 string = fmt.Sprintf("%f", num2)
      fmt.Println(str2)

      var num3 bool = true
      var str3 string = fmt.Sprintf("%t", num3)
      fmt.Println(str3)
  }

Go语言常量

  • 和C语言一样Go语言中的常量也分为整型常量实型常量字符常量字符串常量自定义常量

  • 自定义常量

    • C语言自定义常量: const 数据类型 常量名称 = 值;
      #include <stdio.h>
      int main(int argc, const char * argv[])
      {
          const float PI = 998;
          PI = 110; // 报错
          printf("PI = %d\n", PI );
          return 0;
      }
    
    • Go语言自定义常量: const 常量名称 数据类型 = 值 or const 常量名称 = 值
    package main
    import "fmt"
    func main() {
      //const PI float32 = 3.14
      //PI = 110 // 报错
      //fmt.Println("PI = ", PI )
    
      const PI = 3.14
      PI = 110 // 报错
      fmt.Println("PI = ", PI )
    }
    
    • 除此之外Go语言还支持一次性定义多个常量
    package main
    import "fmt"
    func main() {
      // 多重赋值方式
      const num1, num2 int  = 100, 200
      fmt.Println("num1 = ", num1)
      fmt.Println("num2 = ", num2)
    
      // 常量组方式
      const (
          num3 = 100
          num4 = 200
      )
      fmt.Println("num3 = ", num3)
      fmt.Println("num4 = ", num4)
    
      // 常量组+多重赋值
      const (
          num5, num6 = 100, 200
          num7 = 300
      )
      fmt.Println("num5 = ", num5)
      fmt.Println("num6 = ", num6)
      fmt.Println("num7 = ", num7)
    }
    

  • Go语言自定义常量注意点
    • 定义的局部变量或者导入的包没有被使用, 那么编译器会报错,无法编译运行
    • 但是定义的常量没有被使用,编译器不会报错, 可以编译运行
    package main
    import "fmt"
    func main() {
      // 可以编译运行
      const PI float32 = 3.14
    }
    
    • 在常量组中, 如果上一行常量有初始值,但是下一行没有初始值, 那么下一行的值就是上一行的值
    package main
    import "fmt"
    func main() {
      const (
          num1 = 998
          num2 // 和上一行的值一样
          num3 = 666
          num4 // 和上一行的值一样
          num5 // 和上一行的值一样
      )
      fmt.Println("num1 = ", num1) // 998
      fmt.Println("num2 = ", num2) // 998
      fmt.Println("num3 = ", num3) // 666
      fmt.Println("num4 = ", num4) // 666
      fmt.Println("num5 = ", num5) // 666
    
      const (
          num1, num2 = 100, 200
          num3, num4  // 和上一行的值一样, 注意变量个数必须也和上一行一样
      )
      fmt.Println("num1 = ", num1)
      fmt.Println("num2 = ", num2)
      fmt.Println("num3 = ", num3)
      fmt.Println("num4 = ", num4)
    }
    

  • 枚举常量
    • C语言中枚举类型的本质就是整型常量
    • Go语言中没有C语言中明确意义上的enum定义, 但是可以借助iota标识符来实现枚举类型
  • C语言枚举格式:
 enum 枚举名 {
    枚举元素1,
    枚举元素2,
    … …
 };
    • C语言枚举中,如果没有指定初始值,那么从0开始递增
    #include <stdio.h>
    int main(int argc, const char * argv[])
    {
        enum Gender{
            male,
            female,
            yao,
        };
    //    enum Gender g = male;
    //    printf("%d\n", g); // 0
    //    enum Gender g = female;
    //    printf("%d\n", g); // 1
        enum Gender g = yao;
        printf("%d\n", g); // 2
        return 0;
    }
    
    • C语言枚举中, 如果指定了初始值,那么从指定的数开始递增
    #include <stdio.h>
    int main(int argc, const char * argv[])
    {
        enum Gender{
            male = 5,
            female,
            yao,
        };
    //    enum Gender g = male;
    //    printf("%d\n", g); // 5
    //    enum Gender g = female;
    //    printf("%d\n", g); // 6
        enum Gender g = yao;
        printf("%d\n", g); // 7
        return 0;
    }
    

  • Go语言实现枚举格式
const(
  枚举元素1 = iota
  枚举元素2 = iota
  ... ...
)
    • 利用iota标识符标识符实现从0开始递增的枚举
    package main
    import "fmt"
    func main() {
        const (
            male = iota
            female = iota
            yao = iota
        )
        fmt.Println("male = ", male) // 0
        fmt.Println("male = ", female) // 1
        fmt.Println("male = ", yao) // 2
    }
    
  • iota注意点:
    • 在同一个常量组中,iota从0开始递增, 每一行递增1
    • 在同一个常量组中,只要上一行出现了iota,那么后续行就会自动递增
    package main
    import "fmt"
    func main() {
      const (
          male = iota // 这里出现了iota
          female // 这里会自动递增
          yao
      )
      fmt.Println("male = ", male) // 0
      fmt.Println("male = ", female) // 1
      fmt.Println("male = ", yao) // 2
    }
    
    • 在同一个常量组中,如果iota被中断, 那么必须显示恢复
    package main
    import "fmt"
    func main() {
      const (
          male = iota 
          female = 666 // 这里被中断, 如果没有显示恢复, 那么下面没有赋值的常量都和上一行一样
          yao
      )
      fmt.Println("male = ", male) // 0
      fmt.Println("male = ", female) // 666
      fmt.Println("male = ", yao) // 666
    }
    
    package main
    import "fmt"
    func main() {
      const (
          male = iota 
          female = 666 // 这里被中断
          yao = iota // 这里显示恢复, 会从当前常量组第一次出现iota的地方开始,每一行递增1, 当前是第3行,所以值就是2
      )
      fmt.Println("male = ", male) // 0
      fmt.Println("male = ", female) // 666
      fmt.Println("male = ", yao) // 2
    }
    
    • iota也支持常量组+多重赋值, 在同一行的iota值相同
    package main
    import "fmt"
    func main() {
      const (
        a, b = iota, iota
        c, d = iota, iota
      )
      fmt.Println("a = ", a) // 0
      fmt.Println("b = ", b) // 0
      fmt.Println("c = ", c) // 1
      fmt.Println("d = ", d) // 1
    }
    
    • iota自增默认数据类型为int类型, 也可以显示指定类型
    package main
    import "fmt"
    func main() {
    const (
        male float32 = iota // 显示指定类型,后续自增都会按照指定类型自增
        female
        yao
    )
    fmt.Printf("%f\n", male) // 0.0
    fmt.Printf("%f\n", female) // 1.0
    fmt.Printf("%f\n", yao) // 2.0
    fmt.Println("male = ", reflect.TypeOf(female)) // float32
    }
    
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,117评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,963评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,897评论 0 240
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,805评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,208评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,535评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,797评论 2 311
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,493评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,215评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,477评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,988评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,325评论 2 252
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,971评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,807评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,544评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,455评论 2 266

推荐阅读更多精彩内容

  • 数据类型转换: 1.当赋值符号两边的数据类型不同的时候,数据类型转换是自动的,不需要程序员插手 当给 int 类型...
    Munin_阅读 735评论 0 2
  • 第01章 JAVA简介第02章 基础语法第02章 递归补充第03章 面向对象第04章 异常处理第05章 数组第06...
    顺毛阅读 487评论 0 1
  • Golang是我最喜欢的一门语言,它简洁、高效、易学习、开发效率高、还可以编译成机器码… 虽然它一出世,就饱受关注...
    盘木阅读 3,485评论 0 7
  • 人生自是有情痴,此恨不关风与月 ~~ 与你擦肩 是我心路上最璀璨的历练 惊鸿一瞥的遇见 虽流光一现的短暂 但你一笑...
    逍遥津柳下暉阅读 172评论 0 2
  • 妈妈,我准备好了我的玩具,我们出发吧。 小多宝带上他的背包跟着我一起出门。 带着他去了红树林,走过一片草地的时候,...
    金晶花阅读 255评论 0 1