go의 기본 데이터 유형에 대한 간략한 살펴보기

정수

비트 길이로 나눈 값: 8비트, 16비트, 32비트, 64비트.

부호 있는 정수(int8, int16, int32, int64)에 해당합니다.

부호 없는 정수(uint8, uint16, uint32, uint64)에 해당합니다.

최대 및 최소 수 계산 규칙:

  • 부호 있는 정수: 부호 때문에 비트 수의 가장 높은 비트가 부호를 저장하는 데 사용되고 나머지 비트는 데이터 값을 저장하는 데 사용되므로 n비트 수의 값 범위는 -2^( int8에 해당하는 n-1)^~2^ (n-1)^-1은 -127 ~ 127입니다.
  • 부호 없는 양수: 가장 높은 숫자로 부호를 기록할 필요가 없으며 모든 숫자가 숫자를 나타냅니다. 값 범위는 0 ~ 2^n^-1입니다. int8의 경우 0 ~ 255입니다.

특수 정수 유형

int뿐만 uint아니라 uintptr.

int그리고 uint특정 플랫폼에 따라 크기는 기본 정수 또는 해당 플랫폼에서 가장 계산 효율적인 값과 동일합니다. 동시에 64비트 또는 32비트이지만 둘 다 64비트 또는 32비트 정수로 가정할 수 없습니다. 동일한 하드웨어에서도 다른 컴파일러는 다른 크기를 선택할 수 있습니다.

크기에 관해서는 uintptr명확하지 않습니다. 하지만 확실히 포인터를 잡을 만큼 큽니다. 저수준 프로그래밍에 자주 사용됩니다.

int, , 기타 정수 유형 과 uint길이가 같을 수 있지만 유형은 다릅니다.int32int64..

int합계 uint의 크기 를 결정 하려면

fmt.Println(runtime.GOARCH)		// 看看CPU型号
fmt.Println(strconv.IntSize)	// 这才是int的大小,上面只是提供一个对照

과다

부호가 있건 없건 간에 결과를 계산하는 데 필요한 비트 수가 유형의 범위를 초과하면 이를 오버플 로라고 합니다 . 오버플로된 상위 비트는 자동으로 삭제됩니다.

var i int8 = -128
fmt.Println(i-1)	// 127
var i2 int8 = 127
fmt.Println(i2+1)	// -128
var u uint8 = 0
fmt.Println(u-1)	// 255
var u2 uint8 = 255
fmt.Println(u2+1)	// 0

부동 소수점 숫자

float32, float64. IEEE 754표준을 따르십시오 .

math.MaxFloat32float32유형의 최대값은 다음 과 같습니다 3.4028234663852886e+38.

math.MaxFloat64则是float64类型的最大值:1.7976931348623157e+308

浮点数可以用来表示小数。

十进制下,float32有效位大约是6位。float64有效位大约是15位。

浮点数的打印可以使用:

  1. %g,保留足够的精度显示
  2. %e,使用指数形式显示
  3. %f,使用无指数形式显示
f := 2.71828
fmt.Printf("%g, %[1]e, %[1]f \n", f)	// 2.71828, 2.718280e+00, 2.718280

复数

complex64complex128 ,二者分别由float32float64组成。

使用real函数提取复数的实部,使用imag函数提取复数的虚部。

浮点数或者整数后面加i就会变成一个虚数,且它的实部为0

x := 1+2i
y := 3+4i

布尔值

bool类型就是布尔值,有true(真)和false(假)两个值。

布尔值无法隐式转换成数值,数值也不能转成布尔值。

它的零值是false

一元操作符!表示逻辑取反。!true表示false

字符串

string表示字符串。它是不可变的字节序列。Go中的字符串内部实现用UTF-8编码。

字符串的“长度”与遍历字符串的做法

字符串的“长度”

对字符串调用len函数,获取到的不是字符串的长度(字符的个数),而是字符串的字节数(字节切片的长度)。

如下,尽管字符个数只有6,但字节长度len(s)却有18,这是因为中文字符以UTF-8存储,通常包含3~4个字节。

s := "中文字节数多"
fmt.Println("len: ", len(s))	// len:  18

对字符串使用下标索引操作,会返回对应索引的字节,而不是字符。

s := "中文字节数多"
fmt.Println("len: ", len(s))	// len:  18
for i :=0; i < len(s); i++ {
    fmt.Printf("%d, %[1]c, %[1]T\n",s[i])
}

对应的输出如下:

len: 18
228, ä, uint8
184, ¸, uint8
173, ­, uint8
230, æ, uint8
150, �, uint8
135, �, uint8
229, å, uint8
173, ­, uint8
151, �, uint8
232, è, uint8
138, �, uint8
130, �, uint8
230, æ, uint8
149, �, uint8
176, °, uint8
229, å, uint8
164, ¤, uint8
154, �, uint8

因此不要随便乱用字符串的下标操作,否则可能获得有意想不到的结果。

遍历字符串

由上面的下标操作可以看出,对字符串的下标索引操作会获得单个字节而不是字符,假如现在我们想处理的是UTF-8解码的字符的话,有两种方式,基本思路都是处理成rune类型:

第一种,用UTF-8解码器显式处理这些字符,unicode/utf8包示例。

utf8.RuneCountInString(s)返回字符串转为rune后的个数,Go使用rune代表一个UTF-8字符。

utf8.utf8.DecodeRuneInString(s[i:])处理当前字符串,并算出下一个rune以及它所占的字节数。

s := "What? 中文字节数多"
runeCount := utf8.RuneCountInString(s)
fmt.Println("runeCount:", runeCount)	// runeCount: 12
for i:= 0; i<len(s); {
	r, size:= utf8.DecodeRuneInString(s[i:])
	fmt.Printf("i: %d, r:%q, type:%T \n", i, r, r)
	i += size
}

输出如下:

runeCount: 12
i: 0, r:'W', type:int32
i: 1, r:'h', type:int32
i: 2, r:'a', type:int32
i: 3, r:'t', type:int32
i: 4, r:'?', type:int32
i: 5, r:' ', type:int32
i: 6, r:'中', type:int32
i: 9, r:'文', type:int32
i: 12, r:'字', type:int32
i: 15, r:'节', type:int32
i: 18, r:'数', type:int32
i: 21, r:'多', type:int32

第二种,用range循环,Go会隐式的进行UTF-8解码。

注意,这里的i,指的是字节的下标,而不是字符的下标。

s := "What? 中文字节数多"
for i, r := range s {
    fmt.Printf("i: %d, rune: %q, type: %T \n", i, r, r)
}

输出如下:

i: 0, rune: 'W', type: int32
i: 1, rune: 'h', type: int32
i: 2, rune: 'a', type: int32
i: 3, rune: 't', type: int32
i: 4, rune: '?', type: int32
i: 5, rune: ' ', type: int32
i: 6, rune: '中', type: int32
i: 9, rune: '文', type: int32
i: 12, rune: '字', type: int32
i: 15, rune: '节', type: int32
i: 18, rune: '数', type: int32
i: 21, rune: '多', type: int32

Rune与Byte(字节)

int32的别名是rune,天然适合存储单个文字符号,为Go所采用的。

rune类型值代表一个UTF-8字符。以字节(byte)为单位对Unicode码点作变长编码。现在计算机都用UTF-8来表示单个字符。

字符串的是由“字符”组成的,字符用单引号包裹起来,如:

var b = 'h'
c := '冲'
fmt.Printf("%d, %q \n", b, b)	// 104, 'h'
fmt.Printf("%d, %q \n", c, c)	// 20914, '冲'

字节,byte类型,底层类型是uint8,由8个bit组成,它可以代表一个ASCII码。ASCII码是满足早期计算机的使用的,它用7位表示128个“字符”(ASCII字符):大小写英文字母、数字、标点符号和设备控制符。

字符串与字节slice的转换

字符串底层是一个字节数组,所以可以和[]byte类型互换。

s := "abc"
b := []byte(s)
s2 := string(b)

概念上,[]byte(s)转换操作会分配新的字节数组,拷贝填入s含有的字节,并生成一个slice的引用,指向整个数组。反之,用string(b)也会产生一份副本而不是操作真正的b,以此保证上面s2不变。

字符串不可变

字符串是不可变的,表现在其字符串值不可修改。平时我们看到的字符串修改操作、拼接操作并不改变原有的字符串值,而是将操作后生成新的字符串值赋予原来的变量。

s := "left foot"
t := s
s += ", right foot"

尽管字符串创建后,它底层的字节slice不可变,但是普通的字节slice是可以随意改变的。

var a = []byte{'h', 'e', 'l', 'l', 'o'}
fmt.Printf("%p, %[1]q \n", a)	// 0xc00000a098, "hello"
a[4] = ' '
fmt.Printf("%p, %[1]q \n", a)	// 0xc00000a098, "hell "

由于字符串的不可变以及避免频繁的操作字符串而导致的多次内存分配和复制,可以使用bytes.Buffer类型。

见GOPL的一个例子:

func intsToString(values []int) string {
	var buf bytes.Buffer
	buf.WriteByte('[')
	for i, v := range values {
		if i > 0 {
			buf.WriteString(",")
		}
		fmt.Fprintf(&buf, "%d", v)
	}
	buf.WriteByte(']')
	return buf.String()
}

func main() {
	fmt.Println(intsToString([]int{1, 2, 3})) // [1,2,3]
}

追加ASCII字符可以用writeByte,追加UTF-8编码的文字符号,最好用WriteRune方法。

基本类型的值都是可比较的

基本类型的值都是可比较的,如布尔值、数值、字符串等。

数值的类型转换

很多整型—整型的转换不会引起值的变化,仅告知编译器如何解读这么值。但缩减大小的类型转换,以及整型与浮点型的相互转换,会因此值的改变或者损失精度。

浮点型转整型会舍弃小数部分并向0取整。

var f = 3.526
i := int(f)
fmt.Printf("f: %v, i: %v \n", f, i) // f: 3.526, i: 3 
var i16 = int16(555)
var i8 = int8(i16)
fmt.Printf("i16: %v, i8: %v \n", i16, i8) // i16: 555, i8: 43 

运算符

运算符降序排列:

* 	/ 	% 	<< 	>> 	& 	&^
+ 	- 	| 	^
==	!=	<	<=	>	>=
&&
||

二元运算符分为五大优先级。同级别的运算符满足左结合律,可以用圆括号指定次序。

常量

常量是一种表达式,保证在编译阶段就计算出对应的值。所有常量本质上都属于基本类型:布尔型、字符串或者数字。

常量自编译后,其值恒定不变。

type Integer int

const I Integer = 10

const S string = "important_secret"

const (
	NUM1 = 1
	NUM2 = 2
	NUM3
	NUM4 = 5.5
	STR1 = "STR1"
)

func main() {
	fmt.Printf("I: %v \n", I)
	fmt.Printf("S: %v \n", S)
	fmt.Printf("NUM1: %v \n", NUM1)
	fmt.Printf("NUM2: %v \n", NUM2)
	fmt.Printf("NUM3: %v \n", NUM3)
	fmt.Printf("NUM4: %v \n", NUM4)
	fmt.Printf("STR1: %v \n", STR1)
}

输出如下:

I: 10
S: important_secret
NUM1: 1
NUM2: 2
NUM3: 2
NUM4: 5.5
STR1: STR1

本文正在参加技术专题18期-聊聊Go语言框架

рекомендация

отjuejin.im/post/7120939408051994638
рекомендация