sunwenfei
  • 关于我
  • Golang
    • Goglang基础教程【译】
      • 介绍
        • 安装
        • Hello World
      • 变量、基本类型以及常量
        • 变量
        • 基本类型
        • 常量
      • 函数和包
        • 函数
        • 包
      • 条件、循环流程控制语句
        • if else条件语句
        • switch语句
        • 循环语句
      • 数组、切片、变参函数
        • 数组(Array)
        • 切片(Slice)
        • 变参函数
      • 其他数据类型
        • 映射(Map)
        • 字符串
      • 指针、结构体和方法
        • 指针
        • 结构体
        • 方法
      • 面向对象编程
        • 结构体 vs 类
        • 组合 vs 继承
        • 接口
        • 多态
      • 并发
        • 并发介绍
        • 协程(goroutine)
        • 管道(channel)
        • 带缓存的管道(buffered channel)
        • 协程池
        • 管道选择器(select)
        • 互斥锁(Mutex)
      • Defer
      • 一等公民函数
      • 反射
      • 错误
        • 错误处理
        • 自定义错误类型
        • panic和recover
      • 文件读写
        • 读文件
        • 写文件
    • Golang面向对象编程
    • Golang函数式编程
    • Golang并发编程
    • Golang web服务编程
    • Golang数据结构与算法
  • Shell编程
    • Find命令
  • JavaScript
    • browser
    • Node.JS
    • Deno
  • TypeScript
  • HTTP
    • 【译】通过信鸽理解HTTPS交互原理
  • React
    • React16
      • Hooks
        • 使用React Hooks拉取数据
  • 移动端开发
    • 原生
    • Flutter
    • ReactNative
    • 小程序
  • 前端测试
Powered by GitBook
On this page

Was this helpful?

  1. Golang
  2. Goglang基础教程【译】
  3. 变量、基本类型以及常量

常量

什么是字面量

考虑下面代码:

var a int = 50
var b string = "I love Go"
var c string = b

这里变量a赋值为字面量50,变量b赋值为字面量I love Go,而变量c则赋值为变量b。像5, -89,I love Go,67.89等,在编程语言中称为字面量。

什么是常量

常量是相对于变量而言的,考虑下面代码:

var a int = 50
const b int = 50

这里两个量a和b虽然都是声明为int类型,并且赋值为50,但是a是变量,b是常量。那么常量与变量有什么区别呢?答案是常量不可重新被赋值。

package main

func main() {
    const a = 55
    a = 89 // 给常量重新赋值会报错
}

常量跟变量的另外一个不同点是,常量声明的同时需要赋值,因此下面的写法会报错:

package main

func main() {
    const int a // 先声明
    a = 50 // 再赋值
}

另外需要注意,常量值需要在编译时确定,因此不能将函数调用的返回值赋值给常量。

package main

import (  
    "fmt"
    "math"
)

func main() {  
    fmt.Println("Hello, playground")
    var a = math.Sqrt(4)    // allowed
    const b = math.Sqrt(4)  // not allowed
}

该程序中,a是变量,因此可以赋值为函数调用返回值;但是b是常量,而函数math.Sqrt(4)的执行是运行时,因此会报错。

无类型常量和有类型常量

Golang中每个变量都有对应的类型,比如:

var a int = 10
var b = 20
c := 30

这三种不同的写法,声明的变量a、b、c均为int类型,虽然有显示声明的,有Golang自动推断的,有简写形式。

Golang中的常量与变量不同,常量包括两种:untyped常量(无类型常量)和typed常量(有类型常量)。为了方便理解,这里以香水为例来说明下。我们都知道,兰蔻(Lancome)和欧碧泉(Biotherm)都属于欧莱雅集团,假如他们公司新发明了一款香水:邂逅。

package main

import "fmt"

type Lancome string
type Biotherm string


func main() {
    const perfume = "邂逅" // 无类型常量
    const perfume1 Lancome  = "邂逅" // 有类型常量,类型是兰蔻
    const perfume2 Biotherm = "邂逅" // 有类型常量,类型是欧碧泉
    var perfume3 Lancome = perfume // 合法
    perfume3 = perfume1 // 合法
    perfume3 = perfume2 // 不合法
    fmt.Println(perfume, perfume1, perfume2, perfume3)
}

为了加深理解我们继续深挖香水这个例子。虽然邂逅这款香水是欧莱雅集团出品的,但是在贴标之前是没有品牌属性的,即const perfume = "邂逅",这行代码我们 并未给perfume常量贴标,因此不属于任何品牌,属于无类型常量。但是一旦贴标,比如const perfume2 Biotherm = "邂逅",这行代码我们给perfume2常量贴标,贴上Biotherm品牌标志,即变为有类型常量。有类型常量是贴标产品,因此不能随便再撕下标签,贴上其他品牌的标志,比如perfume3 = perfume2,因此这行代码是不合法的。

初看这个特性难以理解,但是这样使得Golang的常量更加灵活,我们首先声明无类型的常量,后面用起来就会更加灵活,只要类型兼容,想赋值给什么变量就赋值给什么变量。这里再解释下这里所说的类型兼容,比如const str = "邂逅"中无类型常量str本质是一个字符串,与类型string、Lancome均兼容,这里的类型兼容用来描述无类型常量与其他类型的兼容性:

type Lancome string

const str = "邂逅"
var str1 string = str
var perfume1 Lancome = str

字符串常量

字符串常量声明如下:

const hello = "Hello World"

参考前面对无类型常量和有类型常量的解释,这里声明了一个无类型字符串常量hello。 看下下面的代码你可能会疑惑,为什么说hello是无类型的呢,明明打印出了string。

package main

import (  
    "fmt"
)

func main() {  
    const name = "Sam"
    fmt.Printf("type %T value %v", name, name)

}

运行结果如下:

type string value Sam

这里解释下。前面之所以打印出了string,并不是说常量name是Golang的string类型。本质原因是因为这里name是作为了fmt.Printf函数的参数,而该函数这里期望接收string类型,又因为常量"Sam"本身是一个字符串,与string类型兼容,因此才打印出了string。

布尔常量

布尔常量没什么特殊的,很简答,这里仅举个例子:

package main

func main() {  
    const trueConst = true
    type myBool bool
    var defaultBool = trueConst //allowed
    var customBool myBool = trueConst //allowed
    defaultBool = customBool //not allowed
}

数值常量

数值常量包括整型、浮点型以及复数型。

package main

import (  
    "fmt"
)

func main() {  
    const a = 5
    var intVar int = a
    var int32Var int32 = a
    var float64Var float64 = a
    var complex64Var complex64 = a
    fmt.Println("intVar",intVar, "\nint32Var", int32Var, "\nfloat64Var", float64Var, "\ncomplex64Var",complex64Var)
}
intVar 5 
int32Var 5 
float64Var 5 
complex64Var (5+0i)

从下面的程序我们可以看出整型变量、浮点型变量以及复数型变量被赋值常量时的默认类型分别是int,float64,complex128:

package main

import (  
    "fmt"
)

func main() {  
    var i = 5
    var f = 5.6
    var c = 5 + 6i
    fmt.Printf("i's type %T, f's type %T, c's type %T", i, f, c)

}
i's type int, f's type float64, c's type complex128

数值表达式

数值型常量声明时也不可以使用函数调用返回值来初始化,但是可以使用数值表达式来初始化,比如:

package main

import (
    "fmt"
)

func main() {
    const a float64 = 5.9 / 5.9
    fmt.Printf("a's type %T value %v", a, a)
}

执行结果如下:

a's type float64 value 1
Previous基本类型Next函数和包

Last updated 6 years ago

Was this helpful?

这里由于a被声明为了const常量,因此后面再进行赋值会报错。

这段程序中,首先声明的常量perfume就是无类型常量,而后面声明的perfume1和perfume2则均是有类型常量,其常量类型分别是Lancome和Biotherm。虽然都是常量,但是用法却不同,后面声明的变量perfume3是Lancome类型,因此只能赋值为同类型常量perfume1或者无类型常量perfume。

这里由于变量defaultBool是布尔类型,因此可被赋值无类型常量tureConst,但是不能被赋值为类型不相同的有类型常量customBool。

这里常量a是无类型的,值为5,由于是无类型的,因此可以赋值为多种兼容的类型,执行结果如下:

执行结果如下:

Go Playground在线运行
Go Playground在线运行
Go Playground在线运行
Go Playground在线运行
Go Playground在线运行
Go Playground在线运行
Go Playground在线运行
Go Playground在线运行
Go Playground在线运行