变量表示内存中的一个存储区域,该区域有自己的名称(变量名)和类型(数据类型)。
package mainimport "fmt"func main() {var num intfmt.Println("num =", num)
}
结果:num = 0
int数据类型的默认值是0
,其他的稍后介绍
package mainimport "fmt"func main() {var num = 10.1fmt.Println("num =", num)
}
结果:num = 10.1
var
关键字,用:=
声明并赋初值package mainimport "fmt"func main() {num := 10fmt.Println("num =", num)
}
结果:num = 10
package mainimport "fmt"func main() {// 一次声明多个变量var n1, n2, n3 intfmt.Println("n1 =", n1, "n2 =", n2, "n3 =", n3)// 一次声明多个变量并赋初值var a, name, b = 100, "张三", 300fmt.Println("a =", a, "name =", name, "b =", b)// 简写i, j := 10, 20fmt.Println("i =", i, "j =", j)
}
结果:
n1 = 0 n2 = 0 n3 = 0
a = 100 name = 张三 b = 300
i = 10 j = 20
package mainimport "fmt"// 一次声明多个全局变量
var (a = 100b = 200name = "李四"
)func main() {fmt.Println("a =", a, "b =", b, "name =", name)
}
结果:a = 100 b = 200 name = 李四
int
型默认值为0
,string
型默认值为空串我们可以在函数内部使用变量声明的简写方式,比如
a := 10
,但这条语句不能写在函数外部,也就是全局,因为这条语句相当于两条语句:var a int
与a = 10
,而在全局中是不允许有赋值语句的。
Go的数据类型分为基本数据类型和派生/复杂数据类型。
bool
string
int
、int8
、int16
、int32
、int64
uint
、uint8
、uint16
、uint32
、uint64
、uintptr
byte
(uint8
的别名)rune
(int32
的别名,表示一个Unicode
码点)float32
、float64
complex64
、complex128
指针pointer
数组array
结构体struct
管道channel
函数function
切片slice
接口interface
map
类型 | 有无符号 | 占用存储空间 | 表示范围 | 备注 |
---|---|---|---|---|
int8 | 有 | 1字节 | -128 ~ 127 | |
int16 | 有 | 2字节 | -215 ~ 215-1 | |
int32 | 有 | 4字节 | -231 ~ 231-1 | |
int64 | 有 | 8字节 | -263 ~ 263-1 | |
uint8 | 无 | 1字节 | 0 ~ 255 | |
uint16 | 无 | 2字节 | 0 ~ 216-1 | |
uint32 | 无 | 4字节 | 0 ~ 232-1 | |
uint64 | 无 | 8字节 | 0 ~ 264-1 | |
int | 有 | 32位系统占4个字节,64位系统占8个字节 | -231 ~ 231-1,-263 ~ 263-1 | 默认 |
uint | 无 | 32位系统占4个字节,64位系统占8个字节 | 0 ~ 232-1,0 ~ 264-1 | |
rune | 有 | 与int32 一样 | -231 ~ 231-1 | 等价int32 ,表示一个Unicode 码 |
byte | 无 | 与uint8 一样 | 0 ~ 255 | 当要存储字符时选用byte |
int
和uint
的大小与系统有关int
型package mainimport "fmt"func main() {var a = 200// fmt.Printf用来做格式化输出// %T表示类型fmt.Printf("变量a的类型为%T", a)// 结果:// 变量a的类型为int
}
package main// 一次导入多个包
import ("fmt""unsafe"
)func main() {var a = 200fmt.Printf("变量a的类型为%T\n", a)// unsafe.Sizeof用来获取变量所占内存大小,单位:字节fmt.Printf("变量a所占内存大小为%d个字节", unsafe.Sizeof(a))// 结果:// 变量a的类型为int// 变量a所占内存大小为8个字节
}
package mainimport "fmt"func main() {// byte表示范围:0~255var age byte = 20fmt.Printf("年龄是%d岁", age)// 年龄是20岁
}
类型 | 占用存储空间 | 表示范围 | 备注 |
---|---|---|---|
float32 | 4字节 | -3.403E38 ~ 3.403E38 | |
float64 | 8字节 | -1.798E308 ~ 1.798E308 | 默认 |
float64
package mainimport "fmt"func main() {// 十进制数表示var a = 0.1var b = .2 // 小数点不能少// 科学计数法表示var c = 0.0314e2var d = 314e-2fmt.Println(a) // 0.1fmt.Println(b) // 0.2fmt.Println(c) // 3.14fmt.Println(d) // 3.14
}
package mainimport "fmt"func main() {var a float32 = -1.00000019var b float64 = -1.00000019 //这里的'float64'应该省略,因为它是默认的fmt.Println(a)//-1.0000002fmt.Println(b)//-1.00000019
}
float64
,因为它比float32
更精确Go语言中没有专门的字符类型,如果要存储单个字符(字母),一般使用
byte
来保存。
案例演示:
package mainimport "fmt"func main() {var c1 = '我' // 相当于 var c1 rune = '我',这里最好省略'rune'var c2 = '爱' // 相当于 var c2 int32 = '爱',这里最好省略'int32'var c3 = '你'fmt.Printf("%c%c%c", c1, c2, c3) // 我爱你fmt.Println(c1, c2, c3) // 25105 29233 20320fmt.Printf("%T", c1) // int32
}
对上述代码的说明:
byte
类型来保存rune
类型来保存fmt.Printf("%c", c)
转义字符 | 说明 |
---|---|
\t | 制表符 |
\n | 换行符(光标换到下一行) |
\\ | 表示一个\ |
\" | 表示一个" |
\r | 回车符(光标回到本行行首) |
''
引起来的单个字符\?
来将其后的字符转变成特殊的字符常量%c
按格式化输出,就会输出该数字对应的Unicode字符package mainimport "fmt"func main() {var c1 = 20013var c2 = 22269fmt.Printf("%c%c", c1, c2) // 中国
}
package mainimport "fmt"func main() {var c1 = '中'var c2 = '国'fmt.Println(c1 + c2) // 42282
}
bool
类型,布尔类型的数据只能取true
或false
bool
类型占1个字节bool
类型适用于逻辑运算,一般用于程序流程控制案例演示:
package mainimport ("fmt""unsafe"
)func main() {var bo = truefmt.Println("变量bo占", unsafe.Sizeof(bo), "字节")// 变量bo占 1 字节
}
字符串就是一串固定长度的字符连接起来的字符序列。Go的字符串是由单个字节连接起来的,也就是说对于传统的字符串是由字符组成的,而Go的字符串不同,它是由字节组成的。Go的字符串的字节使用UTF-8编码表示Unicode文本。
案例演示:
package mainimport ("fmt""unsafe"
)func main() {var str string = "你好,世界" // string类型可以省略fmt.Println(str)fmt.Printf("string类型占%d个字节", unsafe.Sizeof(str))/*结果:你好,世界string类型占16个字节*/
}
string
类型占16个字节""
(会识别转义字符)、反引号``(以字符串的原生形式输出,包括特殊字符,可以实现防止攻击、输出源代码等效果)package mainimport "fmt"func main() {var str = `
func main() {var str = "你好,世界"fmt.Println(str)
}`fmt.Println(str)
}
结果:
func main() { var str = "你好,世界"fmt.Println(str)
}
+
号必须在上面,原因是Go会为每一行结尾处加上分号,遇到+
号就不会给它加分号package mainimport "fmt"func main() {var str = "你好呀," + "今天过的" + "怎么样," + "有没有学习呢?\n" +"今天过的不错," + "学习也搞了。"fmt.Println(str)
}
结果:
你好呀,今天过的怎么样,有没有学习呢?
今天过的不错,学习也搞了。
数据类型 | 默认值 |
---|---|
整型 | 0 |
浮点型 | 0 |
字符串 | “” |
布尔型 | false |
package mainimport "fmt"func main() {var n int // 整型var c byte // 整型var num float64var bo boolvar str string// %v表示按照变量的原值输出fmt.Printf("n=%v,c=%v,num=%v,bo=%v,str=%v", n, c, num, bo, str)// n=0,c=0,num=0,bo=false,str=
}
Go和Java/C不同,Go在不同类型的变量之间赋值时需要强制类型转换,Go没有自动类型转换。
type(variable)
。type
表示类型;variable
表示变量package mainimport "fmt"func main() {var n1 int32 = 10var n2 = int8(n1)fmt.Printf("n2的类型为%T", n2)// n2的类型为int8
}
package mainimport "fmt"func main() {var n1 int32 = 258 // 二进制表示:1 0000 0010var n2 = int8(n1) // 转换后:0000 0010fmt.Println(n2) // 2
}
package mainimport "fmt"func main() {var n1 int32 = 10var n2, n3 int8n2 = int8(n1) + 127 // 编译能通过n3 = int8(n1) + 128 // 报错:无法将常量 128 转换为类型 int8fmt.Println(n2, n3)
}
func Sprintf(format string, a ...interface{}) string
package mainimport "fmt"func main() {num1 := 10num2 := 10.5c := 'G'b := truevar str stringstr = fmt.Sprintf("%d", num1)fmt.Printf("str的值为字符串%q\n", str)str = fmt.Sprintf("%f", num2)fmt.Printf("str的值为字符串%q\n", str)str = fmt.Sprintf("%c", c)fmt.Printf("str的值为字符串%q\n", str)str = fmt.Sprintf("%t", b)fmt.Printf("str的值为字符串%q\n", str)
}/*结果:
str的值为字符串"10"
str的值为字符串"10.500000"
str的值为字符串"G"
str的值为字符串"true"
*/
strconv
包的函数package mainimport ("fmt""strconv"
)func main() {num1 := 10num2 := 10.5b := truevar str stringstr = strconv.FormatInt(int64(num1), 10)fmt.Printf("str的值为字符串%q\n", str)// 'f'格式6:表示小数位保留6位// 64:表示这个小数是float64str = strconv.FormatFloat(num2, 'f', 6, 64)fmt.Printf("str的值为字符串%q\n", str)str = strconv.FormatBool(b)fmt.Printf("str的值为字符串%q\n", str)
}/*结果:
str的值为字符串"10"
str的值为字符串"10.500000"
str的值为字符串"true"
*/
func Itoa(i int) string
,Itoa是FormatInt(i, 10) 的简写package mainimport ("fmt""strconv"
)func main() {num := 100var str stringstr = strconv.Itoa(num)fmt.Printf("str的值为字符串%q", str)// str的值为字符串"100"
}
strconv
包的函数package mainimport ("fmt""strconv"
)func main() {str1 := "10"var num1 int64// ParseInt函数返回两个值(i int64, err error)// 第一个值才是我们想要的,但它是int64,所以我们声明num时只能指定类型为int64// 下面这种写法表示num接受第一个返回值,然后用'_'忽略第二个返回值num1, _ = strconv.ParseInt(str1, 10, 64)fmt.Printf("num1的值为%v\n", num1) // num1的值为10// ParseFloat函数返回两个值(f float64, err error)str2 := "10.5"var num2 float64num2, _ = strconv.ParseFloat(str2, 64)fmt.Printf("num2的值为%v\n", num2) // num2的值为10.5// ParseBool函数返回两个值(value bool, err error)str3 := "true"var bo boolbo, _ = strconv.ParseBool(str3)fmt.Printf("bo的值为%v\n", bo) // bo的值为true
}
package mainimport ("fmt""strconv"
)func main() {str := "hello"var num int64 = 100num, _ = strconv.ParseInt(str, 10, 64)fmt.Printf("num的值为%v\n", num) // num的值为0var bo = truebo, _ = strconv.ParseBool(str)fmt.Printf("bo的值为%v\n", bo) // bo的值为false
}