第三章基础数据类型

Go语言数据类型分类:基础类型、复合类型、引用类型和接口类型

基础类型:数字、字符串和布尔型

  • 整型

有符号和无符号的整数运算:int8、int16、int32、int64四种不同大小的有符号整数类型

uint8、uint16、uint32、uint64四种无符号整数类型

Unicode字符rune类型是和int32等价的类型,通常用于表示一个Unicode码点,这两个名称可以互换使用

byte是uint8类型的等价类型,byte类型一般用于强调数值是一个原始的数据而不是一个小的整数

无符号整数类型uintptr,没有指定具体的bit大小但是足以容纳指针

在Go语言中,%取模运算符的符号和被取模数的符号总是一致的

除法运算符/的行为依赖于操作数是否全为整数

一个算术运算的结果,不管是有符号或者是无符号的,如果需要更多的bit位才能正确表示的话,就说明计算结果是溢出了。超出的高位的bit位部分将被丢弃

var i int8 = 127
fmt.Println(i, i+1, i*i)

位运算符^作为二元运算符时是按位异或(XOR),当用作一元运算符时表示按位取反

位操作运算符&^用于按位置零(AND NOT):如果对应y中bit位为1,表达式z = x &^ y结果z的对应的bit位为0,否则z对应的bit位等于x相应的bit位的值

左移运算符用零填充右边空缺的bit位,无符号的右移运算也是用0填充左边空缺的bit位,但是有符号数的右移运算会用符号位的值填充左边空缺的bit位

一般更倾向于使用有符号数,无符号数往往只有在位运算或其它特殊的运算场景才会使用,像bit集合、分析二进制文件格式或哈希和加密操作等,通常并不用于仅仅是表达非负数量的场合

当使用fmt包打印一个数值时,可以用%d、%o或%x参数控制输出的进制格式

fmt的两个使用技巧:通常Printf格式化字符串包含多个%参数时将会包含对应相同数量的额外操作数,但是%之后的[1]副词告诉Printf函数再次使用第一个操作数;

%后的#副词告诉Printf在用%o、%x或%X输出时生成0、0x或0X前缀

字符使用%c参数打印,或者是用%q参数打印带单引号的字符

  • 浮点数

Go语言提供了两种精度的浮点数,float32和float64

浮点数的范围极限值可以在math包中找到,常量math.MaxFloat32表示float32能表示的最大数值,大约是3.4e38;对应的math.MaxFloat64常量大约是1.8e308

float32的有效bit位只有23个,其它的bit位用于指数和符号

用Printf函数的%g参数打印浮点数,将采用更紧凑的表示形式打印,并提供足够的精度

对应表格的数据,使用%e(带指数)或%f的形式打印可能更合适

NaN非数,函数math.IsNaN用于测试一个数是否是非数NaN,math.NaN则返回非数对应的值

  • 复数

Go语言提供了两种精度的复数类型:complex64和complex128,分别对应float32和float64两种浮点数精度

内置的complex函数用于构建复数,内建的real和imag函数分别返回复数的实部和虚部

math/cmplx包提供了复数处理的许多函数,例如求复数的平方根函数和求幂函数

fmt.Println(cmplx.Sqrt(-1))

  • 布尔型

一个布尔类型的值只有两种:true和false

布尔值可以和&&和||操作符结合,并且有短路行为

&&的优先级比||高

  • 字符串

一个字符串是一个不可改变的字节序列

非ASCII字符的UTF8编码会要两个或多个字节

不变性意味着如果两个字符串共享相同的底层数据的话也是安全的,这使得复制任何长度的字符串代价是低廉的。同样,一个字符串s和对应的子字符串切片s[7:]的操作也可以安全地共享相同的内存,因此字符串切片操作代价也是低廉的。在这两种情况下都没有必要分配新的内存

Go语言源文件总是用UTF8编码,并且Go语言的文本字符串也以UTF8编码的方式处理,因此可以将Unicode码点也写到字符串面值中

??

一个原生的字符串面值形式是`...`,使用反引号代替双引号。在原生的字符串面值中,没有转义操作;全部的内容都是字面的意思,包含退格和换行,因此一个程序中的原生字符串面值可能跨越多行(译注:在原生字符串面值内部是无法直接写`字符的,可以用八进制或十六进制转义或+"`"链接字符串常量完成)

Unicode每个符号都分配一个唯一的Unicode码点,Unicode码点对应Go语言中的rune整数类型,rune是int32等价类型

UTF8是一个将Unicode码点编码为字节序列的变长编码

??Unicode和UTF8

标准库中strings包提供了许多如字符串的查询、替换、比较、截断、拆分和合并等功能

bytes包也提供了很多类似功能的函数

strconv包提供了布尔型、整型数、浮点数和对应字符串的相互转换,还提供了双引号转义相关的转换

unicode包提供了IsDigit、IsLetter、IsUpper和IsLower等类似功能,它们用于给字符分类。每个函数有一个单一的rune类型的参数,然后返回一个布尔值。ToUpper、ToLower

basename实现

package main

func basename(s string) string {
    for i:=len(s)-1;i>=0;i--{
        if s[i] == '/' {
            s = s[i+1:]
            break
        }
    }
    
    for i:=len(s)-1;i>=0;i--{
        if s[i] == '.' {
            s = s[:i]
            break
        }
    }
    return s
}
package main

import "strings"

func basename2(s string) string {
    slash := strings.LastIndex(s, "/")
    s = s[slash+1:]
    if dot := strings.LastIndex(s, "."); dot>=0 {
        s = s[:dot]
    }
    return s
}

字节slice是可变的[]byte类型,将一个字节slice转到字符串的操作是构造一个字符串拷贝,以保证复制后的字符串是只读的

为了避免转换中不必要的内存分配,bytes包和strings同时提供了许多实用函数。

strings包中的六个函数:func Contains(s, substr string) bool

func Count(s, sep string) int  

func Fields(s string) [] string

func HasPrefix(s, prefix string) bool

func Index(s, sep string) int 

func Join(a []string, sep string) string

bytes包中也对应的六个函数:

func Contains(b, subslice []byte) bool

func Count(s, sep []byte) int

func Fields(s []byte) [][]byte

func HasPrefix(s, prefix []byte) bool

func Index(s, sep []byte) int

func Join(s [][]byte, sep []byte) []byte

bytes包还提供了Buffer类型用于字节slice的缓存。一个Buffer开始是空的,但是随着string、byte或[]byte等类型数据的写入可以动态增长,一个bytes.Buffer变量并不需要初始化,因为零值也是有效的

当向bytes.Buffer添加任意字符的UTF8编码时,最好使用bytes.Buffer的WriteRune方法,但是WriteByte方法对于写入类似'['和']'等ASCII字符则会更加有效。

字符串和数字的转换  strconv包提供这类转换功能

将一个整数转为字符串,一种方法是用fmt.Sprintf返回一个格式化的字符串;另一个方法是用strconv.Itoa() 整数到ASCII

FormatInt和FormatUint函数可以用不同的进制来格式化数字

字符串到整数,可以使用strconv包的Atoi或ParseInt函数,还有用于解析无符号整数的ParseUint函数

  • 常量

常量表达式的值在编译期计算,而不是在运行期

所有常量的运算都可以在编译期完成,这样可以减少运行时的工作,也方便其他编译优化。当操作数是常量时,一些运行时的错误也可以在编译时被发现,例如整数除0、字符串索引越界、任何导致无效浮点数的操作等

iota常量生成器,用于生成一组以相似规则初始化的常量,但是不用每行都写一遍初始化表达式。在一个const声明语句中,在第一个声明的常量所在的行,iota将会被设置为0,然后在每一个有常量声明的行加一

无类型常量

原文地址:https://www.cnblogs.com/liushoudong/p/13029463.html