二:Go编程语言规范-类型
1.类型
布尔值,数值与字符串类型的实例的命名是预声明的。 数组,结构,指针,函数,接口,切片,映射和信道这些复合类型可由类型字面构造。
每个类型 T
都有一个 基本类型:若 T
为预声明类型或类型字面, 其相应的基本类型为 T
本身。否则,T
的基本类型为其 类型声明中所依据类型的基本类型。
type T1 string
type T2 T1
type T3 []T1
type T4 T3
以上 string,T1 和 T2 的基本类型为 string。 []T1,T3 和 T4 的基本类型为 []T1 。
2.类型与值
注意下面说的是类型相同
- 若两个数组类型其元素类型相同且长度相同,那么它们的类型相同。
- 若两个切片类型其元素类型相同,那么它们的类型相同。
- 若两个结构类型其字段序列相同,相应字段名相同,类型相同,标注相同,那么它们的类型相同。 两个匿名字段其名字被认为相同。出自不同包的小写字段名总不相同。
- 若两个指针类型其基础类型相同,那么它们的类型相同。
- 若两个函数类型其形参个数相同,返回值相同,相应形参类型相同,返回值类型相同, 两函数都可变或都不可变,那么它们的类型相同。形参和返回值名无需匹配。
- 若两个接口类型其方法集相同,名字相同,函数类型相同,那么它们的类型相同。 出自不同包的小写方法名总不相同。两接口类型是否相同与方法的次序无关。
- 若两个映射类型其键值类型相同,那么它们的类型相同。
- 若两个信道类型其值类型相同,方向相同,那么它们的类型相同。
3.可赋值性
任何类型都可赋予空白标识符.
4.布尔类型 bool
布尔类型 表示由预声明常量 true 和 false所代表的布尔值的集。 预声明的布尔类型为 bool。
5.数值类型 int等
uint8 所有无符号 8位整数集(0 到 255)
uint16 所有无符号16位整数集(0 到 65535)
uint32 所有无符号32位整数集(0 到 4294967295)
uint64 所有无符号64位整数集(0 到 18446744073709551615) int8 所有带符号 8位整数集(-128 到 127)
int16 所有带符号16位整数集(-32768 到 32767)
int32 所有带符号32位整数集(-2147483648 到 2147483647)
int64 所有带符号64位整数集(-9223372036854775808 到 9223372036854775807) float32 所有IEEE-754 32位浮点数集
float64 所有IEEE-754 64位浮点数集 complex64 所有带float32实部和虚部的复数集
complex128 所有带float64实部和虚部的复数集 byte uint8的别名
rune int32的别名
除 byte 为 uint8 的别名以及 rune 为 int32 的别名外,所有数值类型都是不同的。 当不同的数值类型混合在一个表达式或赋值操作中时,必须进行类型转换。 例如,int32 与 int 是不同的类型, 尽管它们在特定架构上可能有相同的大小。
大小取决于具体实现的预声明数值类型:
uint 32或64位
int 大小与uint相同
uintptr 大到足以存储指针值无解释位的无符号整数
6.字符串类型 string
字符串是不可变的: 一旦被创建,字符串的内容就不能更改。
字符串 s 的长度(即其字节大小)可使用内建函数 len 获取。若该字符串为常量,则其长度即为编译时常量。
字符串的字节可通过整数0 至 len(s)-1 访问。
获取这样一个元素的地址是非法的;若 s[i] 为字符串的第 i 个字节,&s[i] 就是无效的。
x := "ssssssss"
var str interface{} = x[]
b := str.(byte) //断言是否是字节.如果是则b为该值,如果不是则恐慌
fmt.Println(b)
7.数组类型
数组 a 的长度可使用内建函数 len获取, 其元素可通过整数下标 0 到 len(a)-1 寻址。 数组类型总是一维的,但可组合构成多维的类型。
[]byte
[*N] struct { x, y int32 }
[]*float64
[][]int
[][][]float64 // 等价于[2]([2]([2]float64)) a := []int{, , } // 声明了一个长度为3的int数组 b := []int{, , } // 声明了一个长度为10的int数组,其中前三个元素初始化为1、2、3,其它默认为0 c := [...]int{, , } // 可以省略长度而采用`...`的方式,Go会自动根据元素个数来计算长度
8.切片类型 slice
类似于数组,切片是可索引的且拥有一个长度。切片 s 的长度可通过内建函数 len获取;不同于数组的是,切片可在执行过程中被改变, 其元素可通过整数0 到 len(s)-1 寻址。 给定元素的切片下标可能小于它在其基本数组中的下标。
容量 是该扩展的量度: 它是切片的长度和切片往后数组的长度之和;长度达到其容量的切片可通过从原切片 ‘切下’一个新的来创建。 切片 a 的容量可使用内建函数 cap(a) 获取。
var sli2 []int
sli2 = make([]int, , )
sli2[] =
fmt.Println(sli2) sli := make([]int, , )
sli[] =
fmt.Println(sli) sli3 := []int{, }
fmt.Println(sli3)
产生切片与分配数组后再对其进行切片相同,因此这两个例子的结果为相同的切片:
make([]int, 50, 100)
new([100]int)[0:50]
切片是引用的
9.结构类型
通过有类型而无显式字段名声明的字段为 匿名字段,亦称为 嵌入式 字段或该结构中此种类型的嵌入。 这种字段类型必须作为一个类型名 T 或一个非接口类型名的指针 *T来实现, 且 T 本身不能为指针类型。
// 带类型为T1,*T2,P.T3和*P.T4的4个匿名字段的结构
struct {
T1 // 字段名为T1
*T2 // 字段名为T2
P.T3 // 字段名为T3
*P.T4 // 字段名为T4
x, y int // 字段名为x和y
}
以下为非法声明,因为字段名在结构类型中必须是唯一的:
struct {
T // 与匿名字段*T及*P.T相冲突
*T // 与匿名字段T及*P.T相冲突
*P.T // 与匿名字段T及*T相冲突
}
在结构 x 中,若 x.f 为表示字段或方法 f 的合法选择者,则匿名字段的字段或方法 f 即为已提升的。
给定结构类型 S
与名为 T
的类型,包含在结构方法集中的已提升方法如下:
- 若
S
包含一个匿名字段T
,则S
与*S
的方法集均包含带接收者T
的已提升方法。*S
的方法集也包含带接收者*T
的已提升方法。 - 若
S
包含匿名字段*T
,则S
与*S
的方法集均包含带接收者T
或*T
的已提升方法。
- 若
字段声明可后跟一个可选的字符串字面 标注,成为所有相应字段声明中字段的属性。 标注可通过 反射接口 获得,否则就会被忽略。
// 一个对应于时间戳协议缓存的结构.
// 标注字符串定义了协议缓存的字段号.
struct {
microsec uint64 "field 1"
serverIP6 uint64 "field 2"
process string "field 3"
}
10.指针类型
指针类型表示一个所有给定类型变量的指针的集,称为指针的 基础类型。 未初始化的指针的值为 nil。
x:=3
y:=&x //y这时变成了指针,传x的地址
fmt.Println(y, *y) //*y该地址的值
注意:上面的*y中的*在表达式中代表该指针的值,在类型定义中,则代表某类型变量的指针
type strPoint *string func main() {
var strP strPoint
i := "a"
strP = &i
fmt.Println(strP)
}
11.函数类型 func
在Go中函数也是一种变量,我们可以通过type来定义它,它的类型就是所有拥有相同的参数,相同的返回值的一种类型
type typeName func(input1 inputType1 , input2 inputType2 [, ...]) (result1 resultType1 [, ...]) type testInt func(int) bool // 声明了一个函数类型 func a(integer int) bool {
if integer% == {
return false
}
return true
} func b(integer int) bool {
if integer% == {
return true
}
return false
} func filter(slice []int, f testInt) []int { // 声明的函数类型在这个地方当做了一个参数,这里即可以传a,也可以传b
var result []int
for _, value := range slice {
if f(value) {
result = append(result, value)
}
}
return result
}
函数当做值和类型在我们写一些通用接口的时候非常有用,通过上面例子我们看到testInt这个类型是一个函数类型,然后两个filter函数的参数和返回值与testInt类型是一样的,但是我们可以实现很多种的逻辑,这样使得我们的程序变得非常的灵活。
函数签名中的最后一个形参可能有一个带 ... 前缀的类型。 带这样形参的函数被称为 变参函数 它可接受零个或多个实参的函数。
func()
func(x int) int
func(a, _ int, z float32) bool
func(a, b int, z float32) (bool)
func(prefix string, values ...int)
func(a, b int, z float64, opt ...interface{}) (success bool) //for _, n := range arg 来循环参数
func(int, int, float64) (float64, *[]int)
func(n int) func(p *T)
12.接口类型 interface
接口类型指定一个称为 接口 的 方法集。 接口类型变量可存储任何带方法集类型的值,该方法集为此接口的超集。 这种类型表示 实现此接口。未初始化的接口类型变量的值为 nil。
空interface(interface{})不包含任何的method,正因为如此,所有的类型都实现了空interface。空interface对于描述起不到任何的作用(因为它不包含任何的method),但是空interface在我们需要存储任意类型的数值的时候相当有用,因为它可以存储任意类型的数值。
// 定义a为空接口
var a interface{}
var i int =
s := "Hello world"
// a可以存储任意类型的数值
a = i
a = s
一个函数把interface{}作为参数,那么他可以接受任意类型的值作为参数,如果一个函数返回interface{},那么也就可以返回任意类型的值。是不是很有用啊!
13.映射类型 map
映射通过另一类型唯一的 键 集索引,该类型称为键类型。 未初始化的映射值为 nil。
比较操作符 == 和 != 必须由键类型的操作数完全定义; 因此键类型不能是函数,映射或切片。若该键类型为接口类型,这些比较运算符必须由动态键值定义; 失败将导致一个 运行时恐慌.
元素的数量称为长度。 对于映射 m,其长度可使用内建函数 len 获取并可在执行时更改。元素可在执行时使用赋值来添加并通过 下标表达式 来检索;它们也可通过内建函数 delete 删除。
var numbers map[string] int
numbers = make(map[string] int) //注意是=号
numbers["ss"]= m := make(map[string]string)
m["Hello"] = "Bonjour" rating := map[string]float32{"C": , "Go": 4.5, "Python": 4.5, "C++": }
fmt.Println(rating)
map也是一种引用类型,如果两个map同时指向一个底层,那么一个改变,另一个也相应的改变:
14.信道类型 chan
信道提供一种机制使两个并发执行的函数同步执行,并通过传递具体元素类型的值来通信。 未初始化的信道值为 nil。
信道虽然使用make创建,但不是引用的.确保在并发过程中,各个并发的程序(返回值)能够和父环境通信
容量根据元素的数量设置信道中缓存的大小。若容量大于零,则信道是异步的:
若缓存未满(发送)或非空(接收),则通信操作无阻塞成功,且元素在发送序列中被接收。
若容量为零或无,则只有当发送者和接收者都做好准备时通信才会成功。 nil 信道永远不会准备好通信。
信道可通过内建函数close关闭; 接收操作符的多值赋值形式可测试信道是否关闭。
ci := make(chan int)
cs := make(chan string)
cf := make(chan interface{})
channel通过操作符<-
来接收和发送数据
ch <- v // 发送v到channel ch.
v := <-ch // 从ch中接收数据,并赋值给v
举个例子:
package main import "fmt" func sum(a []int, c chan int) {
sum :=
for _, v := range a {
sum += v
}
c <- sum // send sum to c
} func main() {
a := []int{, , , -, , } c := make(chan int)
go sum(a[:len(a)/], c)
go sum(a[len(a)/:], c)
x, y := <-c, <-c // receive from c fmt.Println(x, y, x + y)
}
默认情况下,channel接收和发送数据都是阻塞的,除非另一端已经准备好,这样就使得Goroutines同步变的更加的简单,而不需要显式的lock。所谓阻塞,也就是如果读取(value := <-ch)它将会被阻塞,直到有数据接收。其次,任何发送(ch<-5)将会被阻塞,直到数据被读出。无缓冲channel是在多个goroutine之间同步很棒的工具。
<-
操作符指定信道的 方向,发送 或 接收。 若没有给定方向,那么该信道就是 双向的。 信道可通过类型转换 或 赋值被强制为只发送或只接收。
chan T // 可以被用来发送和接收类型T的值
chan<- float64 // 只能被用来发送浮点数
<-chan int // 只能被用来接收整数
<-
操作符结合最左边的 chan
可能的方式:
chan<- chan int // 等价于 chan<- (chan int)
chan<- <-chan int // 等价于 chan<- (<-chan int)
<-chan <-chan int // 等价于 <-chan (<-chan int)
chan (<-chan int)
二:Go编程语言规范-类型的更多相关文章
- 浅谈Kotlin(二):基本类型、基本语法、代码风格
浅谈Kotlin(一):简介及Android Studio中配置 浅谈Kotlin(二):基本类型.基本语法.代码风格 浅谈Kotlin(三):类 浅谈Kotlin(四):控制流 通过上面的文章,在A ...
- MFC六大核心机制之二:运行时类型识别(RTTI)
上一节讲的是MFC六大核心机制之一:MFC程序的初始化,本节继续讲解MFC六大核心机制之二:运行时类型识别(RTTI). typeid运算子 运行时类型识别(RTTI)即是程序执行过程中知道某个对象属 ...
- Redis 小白指南(二)- 聊聊五大类型:字符串、散列、列表、集合和有序集合
Redis 小白指南(二)- 聊聊五大类型:字符串.散列.列表.集合和有序集合 引言 开篇<Redis 小白指南(一)- 简介.安装.GUI 和 C# 驱动介绍>已经介绍了 Redis 的 ...
- (C/C++学习笔记) 二十三. 运行时类型识别
二十三. 运行时类型识别 ● 定义 运行时类型识别(Run-time Type Identification, RTTI) 通过RTTI, 程序能够使用基类的指针或引用来检查(check)这些指针或引 ...
- HandlerMethodArgumentResolver(二):Map参数类型和固定参数类型【享学Spring MVC】
每篇一句 黄金的导电性最好,为什么电脑主板还是要用铜? 飞机最快,为什么还有人做火车? 清华大学最好,为什么还有人去普通学校? 因为资源都是有限的,我们现实生活中必须兼顾成本与产出的平衡 前言 上文 ...
- 异常处理的方式二:throws+异常类型
package com.yhqtv.demo01Exception; import java.io.File; import java.io.FileInputStream; import java. ...
- Lua 学习笔记(二)语法、类型、值
首先Lua执行的每一段代码都称之为“程序块”,一个程序块也就是一连串的语句或命令,例如一个源码文件或一行代码.Lua语句之间并不需要分隔符,如代码中的换行就不起任何作用,当然为了养成编码习惯当两条或者 ...
- 类型和原生函数及类型转换(二:终结js类型判断)
typeof instanceof isArray() Object.prototype.toString.call() DOM对象与DOM集合对象的类型判断 一.typeof typeof是一个一元 ...
- day2 二、编程语言、python解释器和变量
一.编程语言分类 1.机器语言 直接用计算机能理解的二进制指令编写程序,直接控制硬件,需要了解硬件的操作细节. 2.汇编语言 用英文标签取代二进制编写程序,也是直接控制硬件,也需要了解硬件的操作细节. ...
随机推荐
- JavaScript基础------入门基础
JavaScript他是一种描述性语言,使用JavaScript就是为了能和网页有更好的交互,下面切入主题进行讲解. 一.JavaScript 1.什么是JavaScript JavaScript是一 ...
- js的一些属性
js attribute(): setAttribute():element.setAttribute(name,balue) getAttribute():element.getAttribute( ...
- 类似 Google Tips 页面的卡片式提示和翻转特效
这款 jQuery 插件用于实现类似 Google Tips 页面的卡片式提示和翻转的交互特效.你可以根据自己的需要定制动画效果参数,定义回调函数来控制行为.因为使用了 CSS3,所以只支持 Chro ...
- 基于 Node.js 平台的web开发框架-----express
express官网:---->传送门 express express框架有许多功能,比如路由配置,中间件,对于想配置服务器的前端来说,非常便捷 自从node发展之后,基于nodejs的开发框架 ...
- [deviceone开发]-do_Camera的简单示例
一.简介 do_Camera组件是通过拍照裁剪来生成图片的组件,这个示例直观的展示组件基本的使用方式 二.效果图 三.相关下载 https://github.com/do-project/code4d ...
- 【Bootstrap】入门例子创建
本文简单介绍下如何来使用 Bootstrap,通过引入 Bootstrap,来实现一个最基本的入门例子. 在前一篇博文[Bootstrap]1.初识Bootstrap 基础之上,我们完全可以更加方便快 ...
- C#各种数组直接的数据复制/转换
之前做Opengl程序,用的的C#的SharpGL这个库,里面有各种奇怪绑定的函数,比如原型为: void glInterleavedArrays(uint format, int stride, v ...
- Hadoop 2.5.1集群安装配置
本文的安装只涉及了hadoop-common.hadoop-hdfs.hadoop-mapreduce和hadoop-yarn,并不包含HBase.Hive和Pig等. http://blog.csd ...
- 从angularJS看MVVM
javascript厚积薄发走势异常迅猛,导致现在各种MV*框架百家争雄,MVVM从MVC演变而来,为javascript注入了全新的活力.我工作的业务不会涉及到angularJS[ng]这么重量级的 ...
- iOS开发-canOpenURL: failed for URL: "xx" - error:"This app is not allowed to query for scheme xx"
转载自:http://www.jianshu.com/p/e38a609f786e