目录
- GO语言数据类型
- 格式化输出
- 数据类型转换
- 常量
1、GO语言数据类型
复合数据类型这里不详细赘述,后续会有单独的文章详细讲解。
1.1 整型
有符号整型: int8 int16 int32 int64 int
无符号整型:uint8 uint16 uint32 uint64 uint
其中uint8就是byte型,int16对应 C语言 中的short型,int64对应C语言中的long型
GO语言中还有一些其他的数字类型,如下图:
1.2 浮点型
Go语言提供了两种精度的复数类型:complex64和complex128,分别对应float32和float64两种浮点数精度。内置的complex函数用于构建复数,内建的real和imag函数分别返回复数的实部和虚部。
复数也可以用==和!=进行相等比较。只有两个复数的实部和虚部都相等的时候它们才是相等的。 math/cmplx包提供了复数处理的许多函数,例如求复数的平方根函数和求幂函数。
z := x + yi x = real(z) y = imag(z)
1.3 布尔型
布尔型只有 true 和 false 两个值 ,并且布尔型无法参与计算,也不能和其他类型相互转换。
1.4 字符串类型
一个字符串是一个 不可改变 的字节序列。字符串可以包含任意的数据,包括byte值0,但是通常是用来包 含人类可读的文本。文本字符串通常被解释为采用UTF8 编码 的 Unicode 码点(rune)序列。
其中+操作符将两个字符串 链接 构造一个新字符串。
字符串可以用==和<进行比较;比较通过逐个字节比较完成的,因此比较的结果是字符串自然编码的顺 序。
字符串值也可以用字符串 面值 方式编写,只要将一系列字节序列包含在双引号即可。
字符串的值是不可变的 :一个字符串包含的字节序列永远不会被改变,当然我们也可以给一个字符串变 量分配一个新字符串值。
s := "left foot" t := s s += ", right foot"
这并不会导致原始的字符串值被改变,但是变量s将因为+=语句持有一个新的字符串值,但是t依然是包含原先的字符串值。
1.5 字符
字符串中的每一个元素叫“字符”,定义字符使用 单引号 ‘。GO语言中的字符有两种:
- byte型:uint8的别名,代表一个ASCII码字符
- rune型:int32的别名,代表一个UTF-8字符 ,当需要处理中文等unicode字符集时需要用到rune类型。
var a byte = 'a' var r rune = '中'
2、格式化输出
golang 的fmt 包实现了格式化I/O函数,类似于C的 printf 和 scanf。格式化verb(’verb’)源自C语言但更简单。
2.1 通用
变量值和类型格式化
%v 值的默认格式表示。当输出结构体时,扩展标志(%+v)会添加字段名 %#v 值的Go语法表示 %T 值的类型的Go语法表示 %% 百分号
2.2 布尔值
%t 单词true或false
2.3 整数
%b 表示为 二进制
%c 该值对应的unicode码值
%d 表示为十进制
%o 表示为八进制
%q 该值对应的单引号括起来的go语法字符字面值,必要时会采用安全的转义表示
%x 表示为十六进制,使用a-f
%X 表示为十六进制,使用A-F
%U 表示为Unicode格式:U+1234,等价于"U+%04X"
2.4 浮点数、复数的两个组分
%b 无小数部分、二进制指数的科学计数法,如-123456p-78;参strconv.FormatFloat %e 科学计数法,如-1234.456e+78 %E 科学计数法,如-1234.456E+78 %f 有小数部分但无指数部分,如123.456 %F 等价于%f %g 根据实际情况采用%e或%f格式(以获得更简洁、准确的输出) %G 根据实际情况采用%E或%F格式(以获得更简洁、准确的输出)
2.5 字符串和[]byte
%s 直接输出字符串或者[]byte %q 该值对应的双引号括起来的go语法字符串字面值,必要时会采用安全的转义表示 %x 每个字节用两字符十六进制数表示(使用a-f) %X 每个字节用两字符十六进制数表示(使用A-F)
2.6 指针
%p 表示为十六进制,并加上前导的0x
没有 %u。整数如果是无符号类型自然输出也是无符号的。类似的,也没有必要指定操作数的尺寸(int8,int64)。
宽度通过一个紧跟在百分号后面的十进制数指定,如果未指定宽度,则表示值时除必需之外不作填充。精度通过(可能有的)宽度后跟点号后跟的十进制数指定。如果未指定精度,会使用默认精度;如果点号后没有跟数字,表示精度为0。举例如下:
%f: 默认宽度,默认精度 %9f 宽度9,默认精度 %.2f 默认宽度,精度2 %9.2f 宽度9,精度2 %9.f 宽度9,精度0
2.7 其它flag
+ 总是输出数值的正负号;对%q(%+q)会生成全部是ASCII字符的输出(通过转义); - 在输出右边填充空白而不是默认的左边(即从默认的右对齐切换为左对齐); # 切换格式: 八进制数前加0(%#o),十六进制数前加0x(%#x)或0X(%#X),指针去掉前面的0x(%#p); 对%q(%#q),如果strconv.CanBackquote返回真会输出反引号括起来的未转义字符串; 对%U(%#U),如果字符是可打印的,会在输出Unicode格式、空格、单引号括起来的go字面值; ' ' 对数值,正数前加空格而负数前加负号; 对字符串采用%x或%X时(% x或% X)会给各打印的字节之间加空格; 0 使用0而不是空格填充,对于数值类型会把填充的0放在正负号后面;
3、数据类型转换
类型转换用于将一种数据类型的变量转换为另外一种类型的变量。Go 语言类型转换基本格式如下:
type_name(expression)
- type_name 为类型,expression 为表达式,表达式包括变量、数值、函数返回值等。
- 数据类型发生转换时需要考虑两种类型之间的关系和范围,避免发生数据截断。
- 布尔值无法与其他数据类型进行转换。
3.1 float与 int之间的转换
需要注意float向int转换时的精度损失。
// 这个就很简单了 var a int64 a = 1 var b float64 b = 2.000 //a -- float64 c := float64(a) // b -- int64 d := int64(b)
3.2 int 转 string
- 相当于byte或rune转string
- 如果int数值是ACSII码的编号或者unicode字符集编号,转成string本质就是根据字符集,将对应编码的字符查找出来。
- 如果int数值超出了unicode字符集编号范围,则转成的字符串显示为乱码。
- 例如:19968转string就是中文 “一”
【特别注意】
- ASCII字符集中数字的10进制范围是 [30-39]
- ASCII字符集中大写字母的10进制范围是 [65-90]
- ASCII字符集中小写字母的10进制范围是 [97-122]
- Unicode字符集中汉字的范围是[4e00-9fa5],10进制的范围是[19968-40869]
3.3 stirng 转 int
不允许将字符串转int
4、常量
常量是一个简单值的标识符,在程序运行时,不会被修改的量。
常量中的数据类型只可以是布尔型、数字型(整数型、浮点型和复数)和字符串型。
常量定义后未被使用不会在编译时报错。
4.1 常量的声明
常量的定义格式:
const identifier [type] = value
你可以省略类型说明符 [type],因为编译器可以根据变量的值来推断其类型。
- 显式类型定义: const b string = “abc”
- 隐式类型定义: const b = “abc”
多个相同类型的声明可以简写为:
const c_name1, c_name2 = value1, value2
4.2 常量组(枚举)
常量还可以用作枚举:
const ( Unknown = 0 Female = 1 Male = 2 )
数字 0、1 和 2 分别代表未知性别、女性和男性。
常量可以用len(), cap(), unsafe.Sizeof()函数计算表达式的值。常量表达式中,函数必须是内置函数,否则编译不过。
常量组中如果不指定类型和初始值,则与上一行非空常量的值相同。
const ( a = 10 b c ) // 此时 a b c的值均是 10
4.3 iota
iota,特殊常量,可以认为是一个可以被编译器修改的常量。
iota 在 const关键字出现时将被重置为 0(const 内部的第一行之前),const 中每新增一行常量声明将使 iota 计数一次(iota 可理解为 const 语句块中的行索引)。
iota 可以被用作枚举值:
const ( a = iota b = iota c = iota )
第一个 iota 等于 0,每当 iota 在新的一行被使用时,它的值都会自动加 1;所以 a=0, b=1, c=2 可以简写为如下形式:
const ( a = iota b c )
iota 用法
package main import "fmt" func main() { const ( a = iota //0 b //1 c //2 d = "ha" //独立值,iota += 1 e //"ha" iota += 1 f = 100 //iota +=1 g //100 iota +=1 h = iota //7,恢复计数 i //8 ) fmt.Println(a,b,c,d,e,f,g,h,i) }
以上实例运行结果为:
0 1 2 ha ha 100 100 7 8
再看个有趣的的 iota 实例:
package main import "fmt" const ( i=1<<iota j=3<<iota k l ) func main() { fmt.Println("i=",i) fmt.Println("j=",j) fmt.Println("k=",k) fmt.Println("l=",l) }
以上实例运行结果为:
i= 1 j= 6 k= 12 l= 24
iota 表示从 0 开始自动加 1,所以 i=1<<0 , j=3<<1 ( << 表示左移的意思),即:i=1, j=6,这没问题,关键在 k 和 l,从输出结果看 k=3<<2 , l=3<<3 。
简单描述下执行过程:
- i=1 :左移 0 位,不变仍为 1;
- j=3 :左移 1 位,变为二进制 110, 即 6;
- k=3 :左移 2 位,变为二进制 1100, 即 12;
- l=3 : 左移 3 位,变为二进制 11000,即 24。
这里再次说明: 常量组中如果不指定类型和初始值,则与上一行非空常量的值相同 。