Go數(shù)據(jù)類型
-
C語(yǔ)言的數(shù)據(jù)類型
image -
GO語(yǔ)言數(shù)據(jù)類型
image -
GO數(shù)據(jù)類型占用的內(nèi)存空間
image
package main
import (
"fmt"
"unsafe"
)
func main() {
// 有符號(hào)的整型
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
// 結(jié)論: int會(huì)根據(jù)系統(tǒng)自動(dòng)調(diào)整,如果系統(tǒng)是64的,那么int就會(huì)變成int64,
// 如果系統(tǒng)是32的, 那么int 就會(huì)變成32位
// 無(wú)符號(hào)的整型
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
// 浮點(diǎn)類型
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
}
- 注意點(diǎn):
- 在GO語(yǔ)言中我們可以通過(guò)Sizeof來(lái)計(jì)算數(shù)據(jù)類型占用的內(nèi)存大小
- 使用Sizeof函數(shù)必須導(dǎo)入unsafe這個(gè)包
- 通過(guò)unsafe.Sizeof()來(lái)調(diào)用這個(gè)方法
- Sizeof的首字母必須大寫
- Go語(yǔ)言中int類型,會(huì)根據(jù)系統(tǒng)自動(dòng)調(diào)整占用內(nèi)存的字節(jié)數(shù)
- 如果是64位系統(tǒng), 那么int就是int64, 占用 8個(gè)字節(jié)
- 如果是32位系統(tǒng), 那么int就是int32, 占用 4個(gè)字節(jié)
GO語(yǔ)言變量
- 變量: 可以改變的數(shù)據(jù)稱為變量
- 定義變量: 就是告訴系統(tǒng)需要分配多大的內(nèi)存空間來(lái)存儲(chǔ)數(shù)據(jù)
- 格式:
- 1.var 變量名稱 數(shù)據(jù)類型
- 2.var 變量名稱 數(shù)據(jù)類型 = 值
- 3.var 變量名稱 = 值
- 4.變量名稱 := 值
package main import ( "fmt" ) func main() { // 先定義后初始化 var num int num = 666 fmt.Printf("num = %d\n", num) // 666 // 定義的同時(shí)初始化 var num1 int = 123 fmt.Println("num1 = ", num1) // 定義的同時(shí)初始化, 并省略數(shù)據(jù)類型 var num2 = 234 fmt.Println("num2 = ", num2) // fmt.Println("int sizeof = ", unsafe.Sizeof(num2)) // 定義的同時(shí)初始化, 并省略數(shù)據(jù)類型和var // := 做了兩件事 // 1. 先定義一個(gè)變量 // 2. 給定義的變量賦值 num3 := 100 fmt.Println("num3 = ", num3) // num4 int:= 23 // := 定義變量的同時(shí)不能添加數(shù)據(jù)類型 var num5 := 555 // := 定義變量的同時(shí)不能添加 var fmt.Println("num4 = ", num5) }
連續(xù)定義多個(gè)變量
- 格式:
- 1.可以通過(guò)逗號(hào)來(lái)定義多個(gè)變量
// 先定義變后初始化 var a , b , c int a = 1 b = 2 c = 3 // 定義變量的同時(shí)初始化 var a , b, c int = 1, 2, 3- 2.可以使用變量組來(lái)同時(shí)定義多個(gè)變量
// 先定義變量后初始化 var( a int b int c int ) a = 1 b = 2 c = 3 // 定義變量同時(shí)初始化 var ( a int = 1 b int = 2 c int = 3 ) // 注意點(diǎn): 變量組中不能使用 := 來(lái)定義變量 // var ( // a := 1 // b := 2 // )
定義變量的注意點(diǎn):
- 定義變量的時(shí)候, 如果省略數(shù)據(jù)類型那么系統(tǒng)會(huì)自動(dòng)根據(jù)數(shù)值推斷出變量的數(shù)據(jù)類型
- 使用 := 定義變量的時(shí)候, 那么不能寫var 也不能寫數(shù)據(jù)類型
- 使用 := 定義變量的時(shí)候, 只能定義局部變量不能定義全局變量
- 使用 := 定義變量的時(shí)候, 變量組中不能使用 := 的格式
- 使用 := 定義多個(gè)變量的時(shí)候, 變量如果已經(jīng)定義過(guò)了那么將退化成賦值操作
// 定義一個(gè)變量
var num int = 234
// 對(duì)于num已經(jīng)定義過(guò)了, 那么將退化成賦值操作
num , value := 666, 777
fmt.Println("num = ", num, "value = ", value)
- 重復(fù)定義變量編譯報(bào)錯(cuò)
package main
import "fmt"
func main() {
num := 234
num := 666
fmt.Println("num = ", num)
}
全局變量和局部變量
- 局部變量:
- 含義: 定義在函數(shù)內(nèi)部的變量,以及函數(shù)的形參就稱為局部變量
- 作用域: 從定義的哪一行開(kāi)始到遇到}和return,到代碼塊結(jié)束就釋放
- 生命周期: 從程序運(yùn)行到哪一行才分配存儲(chǔ)空間, 離開(kāi)作用域就釋放空間
- 全局變量:
- 含義: 定義在函數(shù)外部的變量稱為全局變量
- 作用域: 從定義哪一行開(kāi)始到文件的結(jié)尾
- 生命周期: 程序一啟動(dòng)就分配存儲(chǔ)空間, 知道程序結(jié)束
- 注意點(diǎn):
- GO語(yǔ)言中不管是定義局部變量還是全局變量都不能出現(xiàn)同名的變量
- GO語(yǔ)言中,如果定義一個(gè)局部變量, 但是沒(méi)用使用這個(gè)變量, 編譯報(bào)錯(cuò)
- GO語(yǔ)言中,如果定義一個(gè)全局變量, 但是沒(méi)用使用這個(gè)變量, 編譯不會(huì)報(bào)錯(cuò)
數(shù)值類型和字符串類型之間的轉(zhuǎn)換
- GO語(yǔ)言中只有顯示轉(zhuǎn)換, 沒(méi)有隱式轉(zhuǎn)換
- 數(shù)據(jù)類型一般用于除了字符串和布爾類型以外的其他基本類型的轉(zhuǎn)換
package main
func main() {
// go語(yǔ)言中只有顯示轉(zhuǎn)換沒(méi)有隱式轉(zhuǎn)換
// 格式:數(shù)據(jù)類型(被轉(zhuǎn)換的數(shù)據(jù))
num int = 3.14 // 報(bào)錯(cuò)
fmt.Println("num = ", num)
不能對(duì)一個(gè)常量進(jìn)行類型的強(qiáng)行轉(zhuǎn)換
var num1 int = int(3.14)
fmt.Println("num1 = ", num1)
// 正確做法
// go語(yǔ)言中數(shù)據(jù)類型必須一模一樣才能直接賦值
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 本質(zhì)
fmt.Println("num4 = ", num4) // 97
var ch1 rune = '好'
var num5 int32 = ch1
fmt.Println("num5 = ", num5) // 22909 UTF -8
// bool 類型不能轉(zhuǎn)換為整型
//var flag bool = false
//var num6 int = flag
//fmt.Println("num6 = ", num6)
// 整型也可以轉(zhuǎn)換成字符類型, 但是不推薦使用
//var num7 int = 97
//var str string = string(num7)
//fmt.Println("str = ", str) // a
}
- 基本數(shù)據(jù)類型轉(zhuǎn)換成字符串類型
- 方法一: strconv.FormatXxx()
- 方法二: strconv.Itoa()
package main
import (
"fmt"
"strconv"
"unsafe"
)
func main() {
// 基本數(shù)據(jù)類型轉(zhuǎn)換為字符串類型
// 1. strconv.FormatXxx()
// 2. strconv.Itoa()
// strconv.FormatInt()
// func FormatInt(i int64, base int) string
// 第一個(gè)參數(shù): 需要轉(zhuǎn)換的整數(shù), 必須是int64類型的
// 第二個(gè)參數(shù): 轉(zhuǎn)換為多少進(jìn)制的字符串
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
// 第一個(gè)參數(shù): 需要轉(zhuǎn)換的小數(shù)
// 第二個(gè)參數(shù): 按照什么格式轉(zhuǎn)換 'f' 小數(shù)格式, 'e' 指數(shù)格式
// 第三個(gè)參數(shù): 保留多少位小數(shù), 傳入 -1按照原始類型的精度保留
// 第四個(gè)參數(shù): 原始類型的標(biāo)志 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
}
- 字符類型轉(zhuǎn)換為基本數(shù)據(jù)類型
- 方法一: strconv.ParseXxx()
- 方法二: strconv.Atoi()
package main
import (
"fmt"
"strconv"
)
func main() {
// Go語(yǔ)言中字符串類型轉(zhuǎn)換為基本數(shù)據(jù)類型
// strconv.ParseXxx()
// strconv.Atoi()
// strconv.ParseInt()
// func ParseInt(s string, base int, bitSize int) (i int64, err error)
// 第一個(gè)參數(shù): 需要轉(zhuǎn)換的字符串
// 第二個(gè)參數(shù): 被轉(zhuǎn)化的字符串保存的整數(shù)是多少進(jìn)制的(原來(lái)的字符是多少進(jìn)制的)
// 第三個(gè)參數(shù): 期望轉(zhuǎn)換為多少位的整數(shù)
// 返回值有兩個(gè)
// 第一個(gè)返回值: 轉(zhuǎn)后之后的數(shù)值, 是int64 類型
// 第二個(gè)返回值: 如果轉(zhuǎn)換成功返回nil, 如果轉(zhuǎn)換失敗就不是nil
var str1 = "1010"
// num, err := strconv.ParseInt(str1, 10, 8)
num, err := strconv.ParseInt(str1, 2, 8)
if err != nil{
fmt.Println("轉(zhuǎn)換失敗")
}else{
fmt.Println("num = ", num) // 9
fmt.Printf("%T ", num) // int64
}
// strconv.ParseFloat()
//func ParseFloat(s string, bitSize int) (float64, error)
// 第一個(gè)參數(shù): 需要轉(zhuǎn)換的字符串
// 第二個(gè)參數(shù): 要將字符串中的小數(shù)轉(zhuǎn)換為單精度還是雙精度, 單精度傳入32, 雙精度傳入64
// 返回兩個(gè)返回值
// 第一個(gè)返回值: 轉(zhuǎn)換成功之后的小數(shù), float64類型
// 第二個(gè)返回值: 轉(zhuǎn)換成功返回 nil, 轉(zhuǎn)換失敗不為 nil
str2 := "3.123456789"
num1, err := strconv.ParseFloat(str2, 32)
if err != nil{
fmt.Println("轉(zhuǎn)換失敗")
}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)
// 傳入一個(gè)字符串
// 返回兩個(gè)值, 第一個(gè)是轉(zhuǎn)換成功后的數(shù), 第二個(gè)返回值是 : 轉(zhuǎn)換成功返回nil,
var str4 string = "99"
num2, err := strconv.Atoi(str4)
if err != nil{
fmt.Println("轉(zhuǎn)換失敗")
}else{
fmt.Println("num2 = ", num2)
}
}
GO語(yǔ)言常量
- GO語(yǔ)言常量分為整型常量, 實(shí)型常量, 字符常量, 字符串常量, 自定義常量
- 自定義常量
- 格式: const 常量名稱 數(shù)據(jù)類型 = 值 或者 const 常量名稱 = 值
package main
import "fmt"
func main() {
// 格式: const 變量名稱 數(shù)據(jù)類型 = 值
const num1 int = 222
// num1 = 111 // 常量不能賦值, 否則報(bào)錯(cuò)
fmt.Println("num1 = ", num1)
// 給多個(gè)變量賦值
// 格式: const 變量名1 , 變量名2 數(shù)據(jù)類型 = 值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)
// 變量組的定義多個(gè)變量的注意點(diǎn)
// 如果常量沒(méi)有賦值, 那么默認(rèn)值就是上一行的取值
//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
}
- 注意點(diǎn):
- 不能給常量賦值, 會(huì)報(bào)錯(cuò)
- 在常量組中, 如果常量沒(méi)有賦值, 那么值為上一行的值
- 枚舉常量
- 格式
const (
枚舉元素1 = 值
枚舉元素2 = 值
)
package main
import "fmt"
func main() {
// 枚舉類型的本質(zhì)就是整型常量
// Go語(yǔ)言和C語(yǔ)言一樣都是從0開(kāi)始遞增, 每行遞增1
/*const(
male = iota
female = iota
yy = iota
)*/
// 等同于下面的寫法
const(
male = iota
female
yy
)
// 只要有一行出現(xiàn)了iota, 那么后續(xù)會(huì)自動(dòng)遞增
fmt.Println("male = ", male) // 0
fmt.Println("female = ", female) // 1
fmt.Println("yy = ", yy) // 2
// 如果常量組中被打斷了, 那么就不會(huì)繼續(xù)遞增了,
// 而是會(huì)按照常量的的方式處理, 不賦值就會(huì)等于上一行的值
const (
a = iota
b = 888
c
)
fmt.Println("a = ", a) // 0
fmt.Println("b = ", b) // 888
fmt.Println("c = ", c) // 888
// 如果常量組中的iota被打斷了, 但是后續(xù)又恢復(fù), 那么前面有多少行,就會(huì)遞增多少
const (
num1 = iota
num2 = 111
num3 = iota
)
fmt.Println("num1 = ",num1) // 0
fmt.Println("num2 = ",num2) // 111
fmt.Println("num3 = ",num3) // 2
}
- 注意點(diǎn):
- Go語(yǔ)言和C語(yǔ)言的枚舉一樣,利用iota標(biāo)識(shí)符從0開(kāi)始遞增,每行增加1
- 在常量組中, iota只要上一行出現(xiàn)了, 那么下一行不賦值也會(huì)遞增
- 但是如果常量組中, 被常量打斷了, 那么就會(huì)等于上一行的值
- 常量組如果被打斷,后續(xù)又恢復(fù),那么前面有多少行就會(huì)遞增多少


