一、基本类型

清晰完备的预定义基础类型,使得开发跨平台应用时无须过多考虑符合和长度差异。

类型 长度 默认值 说明
bool 1 false  
byte 1 0 uint8
int, uint 4, 8 0 默认整数类型,依据目标平台,32 或 64 位
int8, uint8 1 0 -128 ~ 127,0 ~ 125
int16, uint16 2 0 -32,768 ~ 32,767,0 ~ 65,535
int32, uint32 4 0 -21亿 ~ 21亿,0 ~ 42亿
int64, uint64 8 0  
float32 4 0.0  
float64 8 0.0 默认浮点数类型
complex64 8    
complex128 16    
rune 4 0 Unicode Code Point, int32
uintptr 4, 8 0 足以存储指针的 uint
string   "" 字符串,默认值为空字符串,而非 NULL
array     数组
struct     结构体
function   nil 函数
interface   nil 接口
map   nil 字典,引用类型
slice   nil 切片,引用类型
channel   nil 通道,引用类型

支持八进制、十进制以及科学计数法。标准库 math 定义了各数字类型的取值范围。

import (
"fmt"
"math"
) func main() {
a, b, c := 100, 0144, 0x64 fmt.Println(a, b, c)
fmt.Printf("0b%b, %#o, %#x\n", a, a, a) fmt.Println(math.MinInt8, math.MaxInt8)
}

输出:

100 100 100
0b1100100, 0144, 0x64 -128 127

标准库 strconv 可在不同进制(字符串)间转换。

import (
"strconv"
) func main() {
a, _ := strconv.ParseInt("1100100", 2, 32)
b, _ := strconv.ParseInt("0144", 8, 32)
c, _ := strconv.ParseInt("64", 16, 32) println(a, b, c) println("0b" + strconv.FormatInt(a, 2))
println("0" + strconv.FormatInt(a, 8))
println("0x" + strconv.FormatInt(a, 16))
}

输出:

100 100 100
0b1100100
0144
0x64

使用浮点数时,须注意小数位的有效精度,相关细节可参考 IEEE-754 标准。

func main()  {
var a float32 = 1.1234567899 // 注意:默认浮点数类型是 float64
var b float32 = 1.12345678
var c float32 = 1.123456781 println(a, b, c)
println(a == b, a == c)
fmt.Printf("%v %v, %v\n", a, b, c)
}

输出:

+1.123457e+000 +1.123457e+000 +1.123457e+000
true true
1.1234568 1.1234568, 1.1234568

别名

在官方的语言规范中,专门提到 两个 别名。

byte        alias for unit8
rune        alias for unit32

别名类型无须转换,可直接赋值。

func test(x byte) {
println(x)
} func main() {
var a byte = 0x11
var b uint8 = a
var c uint8 = a + b test(c)
}

但这并不表示,拥有相同底层结构的就属于别名。就算在 64位 平台上 int 和 int64 结构完全一致,也分属不同类型,须显式转换。

func add(x, y int) int {
return x + y
} func main() {
var x int = 100
var y int64 = x // 错误:cannot use x (type int) as type int64 in assignment add(x, y) // 错误:cannot use y (type int64) as type int in argument to add
}

二、引用类型

所谓引用类型(reference type),特指 slice 、map 、channel 这三种预定义类型。相比 数字 、数组 等类型,引用类型 拥有更复杂的存储结构。除分配内存外,他们还须初始化一系列属性,诸如 指针 、长度 ,甚至包括哈希分布、数据队列等。

内置函数 new() 按指定类型长度分配零值内存,返回指针,并不关心类型内部结构和初始化方式。而 引用类型 则必须使用 make() 函数创建,编译器会将 make() 转换为目标类型专用的创建函数(或指令),以确保完成全部内存分配和相关属性初始化。

// test.go 文件

package main

func mkslice() []int  {
s := make([]int, 0, 10)
s = append(s, 100)
return s
} func mkmap() map[string]int {
m := make(map[string]int)
m["a"] = 1
return m
} func main() {
m := mkmap()
println(m["a"]) s := mkslice()
println(s[0])
}

输出:

$ go build -gcflags "-l"  // 禁用函数内联

$ go tool objdump -s "main\.mk" test

TEXT main.mkslie(SB) test.go
CALL runtime.makeslice(SB) TEXT main.mkmap(SB) test.go
CALL runtime.makemap(SB)

除 new() / make() 函数外,也可用 初始化表达式,编译器生成的指令基本相同。

当然,new() 函数也可为引用类型分配内存,但这是不完整创建。以字典(map)为例,它仅分配了字典类型本身(实际就是个指针包装)所需内存,并没有分配键值存储内存,也没有初始化散列桶等内部属性,因此它无法正常工作。

import "fmt"

func main() {
p := new(map[string]int) // 函数 new 返回指针
m := *p
m["a"] = 1 // 报错:panic: assignment to entry in nil map [运行期错误]
fmt.Println(m)
}

三、类型转换

隐式转换造成的问题远大于它带来的好处。

除 常量 、别名类型 以及 未命名类型 外,Go 强制要求使用显示类型转换。加上不支持操作符重载,所以我们总是能确定语句及表达式的明确含义。

func main() {
a := 10
b := byte(a)
c := a + int(b) // 混合类型表达式必须确保类型一致
fmt.Println(c)
}

同样不能讲 非bool 类型结果当作  true/false 使用。

func main() {
x := 100 var b bool = x // 报错:cannot use x (type int) as type bool in assignment if x { // 报错:non-bool x (type int) used as if condition
}
}

语法歧义

如果转换的目标 指针 、单向通道 或 没有返回值的函数 类型,那么必须使用 括号(),以避免造成语法分解错误。

func main() {
x := 100
p := *int(&x) // 报错:cannot convert &x (type *int) to type int
// invalid indirect of int(&x) (type int)
println(p)
}

正确的做法是用括号,让编译器将 *int 解析为指针类型。

(*int)(p)            --> 如果没有括号 -->      *(int(p))
(<-chan int)(c)                               <-(chan  int(c))
(func())(x)                                   func() x

func() int (x)       --> 有返回值的函数类型可省略括号,但依然建议使用。
(func() int) (x)     使用括号后,更易阅读

四、自定义类型

使用关键字 type 定义用户自定义类型,包括基于现有基础类型创建,或者是 结构体 、函数类型 等。

type flags byte

const (
read flags = 1 << iota
write
exec
) func main() {
f := read | exec
fmt.Printf("%b\n", f) // 输出二进制标志位
}

输出:

101

和 var 、const 类似,多个 type 定义可以合并成组,可在 函数 或 代码块内定义局部类型。

func main() {
type ( // 组
user struct { // 结构体
name string
age uint8
} event func(string) bool // 函数类型
) u := user{"Tom", 20}
fmt.Println(u) var f event = func(s string) bool {
println(s)
return s != ""
} f("abc")
}

输出:

{Tom 20}
abc

即便指定了基础类型,也只表明它们有相同底层数据结构,两者间不存在任何关系,属完全不同的两种类型。除操作符外,自定义类型不会继承基础类型的其他信息(包括方法)。不能视作别名,不能隐式转换,不能直接用于比较表达式。

func main() {
type data int
var d data = 10 var x int = d // 错误:annot use d (type data) as type int in assignment
println(x) println(d == x) // 错误:invalid operation: d == x (mismatched types data and int)
}

未命名类型

与有明确标识符的 bool 、int 、string 等类型相比,数组 、切片 、字典 、通道 等类型与具体元素类型或长度等属性有关,故称作 未命名类型(unnamed type)。当然,可用 type 为其提供 具体名称,将其改变为 命名类型(named type)。

具有相同声明的未命名类型视作同一类型。

  • 具有相同基类型的指针;
  • 具有相同元素类型 和 长度的数组(array);
  • 具有相同元素类型的切片(slice);
  • 具有相同键值类型的字典(map);
  • 具有相同数据类型及操作方向的通道(channel);
  • 具有相同字段序列(字段名、字段类型、标签,以及字段顺序)的结构体(struct);
  • 具有相同签名(参数和返回值列表,不包括参数名)的函数(func);
  • 具有相同方法集(方法名、方法签名,不包括顺序)的接口(interface);

容易被忽视的是 struct tag,它也属于类型组成部分,而不仅仅是元数据描述。

func main() {
var a struct { // 匿名结构类型
x int `X`
s string `S`
} var b struct {
x int
s string
} b = a // 错误:cannot use a (type struct { x int "X"; s string "S" }) as type struct { x int; s string } in assignment fmt.Println(b)
}

同样,函数的参数顺序也属签名组成部分。

func main() {
var a func(int, string)
var b func(string, int) b = a // 错误:cannot use a (type func(int, string)) as type func(string, int) in assignment b("s", 1)
}

未命名类型转换规则:

  • 所属类型相同;
  • 基础类型相同,且其中一个是未命名类型
  • 数据类型相同,将双向通道赋值给单向通道,且其中一个为未命名类型;
  • 将默认值 nil 赋值给 切片、字典、通道、指针、函数 或 接口;
  • 对象实现了目标接口;
func main() {
type data [2]int
var d data = [2]int{1, 2} // 基础类型相同,右值为 未命名类型 fmt.Println(d) a := make(chan int, 2)
var b chan<- int = a // 双向通道 转换为 单向通道,其中 b 为 未命名类型 b <- 2
}

《Go学习笔记 . 雨痕》类型的更多相关文章

  1. 《Go学习笔记 . 雨痕》流程控制(if、switch、for range、goto、continue、break)

    Go 精简(合并)了流控制语句,虽然某些时候不够便捷,但够用. if...else... 条件表达式值必须是布尔类型,可省略括号,且左花括号不能另起一行. func main() { x := 3 i ...

  2. 《Go学习笔记 . 雨痕》方法

    一.定义 方法 是与对象实例绑定的特殊函数. 方法 是面向对象编程的基本概念,用于维护和展示对象的自身状态.对象是内敛的,每个实例都有各自不同的独立特征,以 属性 和 方法 来暴露对外通信接口.普通函 ...

  3. 《Go学习笔记 . 雨痕》反射

    一.类型(Type) 反射(reflect)让我们能在运行期探知对象的类型信息和内存结构,这从一定程度上弥(mi)补了静态语言在动态行为上的不足.同时,反射还是实现元编程的重要手段. 和 C 数据结构 ...

  4. java学习笔记01--数据类型

    java学习笔记01--数据类型 java数据类型划分 分为两大类型: 1)基本数据类型:类似于普通的值. 2)引用数据类型:传递的是内存的地址. 浮点类型实际上就是表示小数. java基本数据类型 ...

  5. Hadoop学习笔记—5.自定义类型处理手机上网日志

    转载自http://www.cnblogs.com/edisonchou/p/4288737.html Hadoop学习笔记—5.自定义类型处理手机上网日志 一.测试数据:手机上网日志 1.1 关于这 ...

  6. C#学习笔记之值类型与引用类型

    [TOC] C#学习笔记之值类型与引用类型 1.值类型与引用类型 1.1 深层区别 值类型与引用类型有不同的内存分布,这导致了不同的内存管理机制: 值类型由OS负责内存管理 引用类型由垃圾回收器(GC ...

  7. WebGL three.js学习笔记 6种类型的纹理介绍及应用

    WebGL three.js学习笔记 6种类型的纹理介绍及应用 本文所使用到的demo演示: 高光贴图Demo演示 反光效果Demo演示(因为是加载的模型,所以速度会慢) (一)普通纹理 计算机图形学 ...

  8. [读书笔记]C#学习笔记三: C#类型详解..

    前言 这次分享的主要内容有五个, 分别是值类型和引用类型, 装箱与拆箱,常量与变量,运算符重载,static字段和static构造函数. 后期的分享会针对于C#2.0 3.0 4.0 等新特性进行. ...

  9. C#学习笔记二: C#类型详解

    前言 这次分享的主要内容有五个, 分别是值类型和引用类型, 装箱与拆箱,常量与变量,运算符重载,static字段和static构造函数. 后期的分享会针对于C#2.0 3.0 4.0 等新特性进行. ...

随机推荐

  1. EM算法理解

    一.概述 概率模型有时既含有观测变量,又含有隐变量,如果概率模型的变量都是观测变量,那么给定数据,可以直接利用极大似然估计法或者贝叶斯估计法估计模型参数.但是,当模型同时又含有隐变量时,就不能简单地使 ...

  2. perl6 HTTP::UserAgent (2)

    http://www.cnblogs.com/perl6/p/6911166.html 之前这里有个小小例子, 这里只要是总结一下. HTTP::UserAgent包含了以下模块: --------- ...

  3. yum安装失败:ublic key for **.rpm is not installed

    yum install mysql-server --nogpgcheck package_need_to_install

  4. linux服务器如何添加sudo用户

    1. 编辑 vi /etc/ssh/sshd_config 文件,修改默认端口:默认Port为22,并且已经注释掉了,修改是把注释去掉,并修改成其它的端口. 原来用默认端口:22修改为:8975 (这 ...

  5. Owin中间件动手做

    摘要:本文目的是了解Owin基本原理.讲述如何从控制台创建一个自宿主的OwinHost,然后再编写一两个中间件 准备工作 首先通过VisualStudio创建一个控制台应用 然后添加Owin的Nuge ...

  6. elasticsearch安装kibana插件

    1.下载 2.解压将解压后的文件放到D:\DevTools\kibana-4.6.0-windows-x86路径下 3.修改配置文件D:\DevTools\kibana-4.6.0-windows-x ...

  7. django之class Meta

    通过一个内嵌类 "class Meta" 给你的 model 定义元数据, 类似下面这样: class Foo(models.Model): bar = models.CharFi ...

  8. HDU 2512 一卡通大冒险(第二类斯特林数+贝尔数)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2512 题目大意:因为长期钻研算法, 无暇顾及个人问题,BUAA ACM/ICPC 训练小组的帅哥们大部 ...

  9. Java编程的逻辑 (32) - 剖析日期和时间

    本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http:/ ...

  10. vs2010下sort比较函数链接错误问题

    环境:win7 + vs2010 + C++ 实现vector的sort算法,在类的头文件中写入比较函数时会出现链接错误: error LNK2005: "bool __cdecl comp ...