在内存中的形式

首先看一下在go中,一些基础类型在内存中是以什么形态存在的,如下图所示:

变量j的类型是int32, 而变量i的类型是int,两者不是同一个类型,所以赋值操作i=j是一种类型错误cannot use j (type int32) as type int in assignment

正确的方式应该是

	i := int(7)
j := int32(7)
i = int(j)

结构体的域在内存中是紧密排列的。

静态类型和底层类型

byte是Go的静态类型,uint8是Go的底层类型

rune是int32的别名,用于表示unicode字符。通常在处理中文的时候需要用到它

string类型

定义在go-1.8.3/go/src/runtime/string.go

type stringStruct struct {
str unsafe.Pointer
len int
}

两个属性:一个指针,一个int型的长度,都是私有成员!

string类型类型在Go语言的内存模型中用一个2字长的数据结构表示。 从上图可以看出,其实多个string是共享一个存储的。

str[i:j]进行字符串切片操作,会得到一个新的type stringStruct struct对象,该对象的指针依然还是指向str的底层存储,长度为j-i。 这说明字符串切分不涉及内存分配或复制操作,其效率等同于传递下标。

内建函数len()对string类型的操作是直接从底层结构中取出len值,而不需要额外的操作

slice类型

定义在/go-1.8.3/src/runtime/slice.go

type slice struct {
array unsafe.Pointer
len int
cap int
}

显然,type slice struct和上面的type stringStruct struct很类似,只是多了一个cap属性。

一个slice是一个底层数组的部分引用。同理,对底层数据进行切片操作也不会涉及到内存分配或复制操作,仅仅是新建了一个type slice struct对象而已!

需要注意的是,在上图中,y[0:4]是有效的,打印出来的结果会是[3,5,7,11]

由于slice是不同于指针的多字长结构,分割操作并不需要分配内存,甚至没有通常被保存在堆中的slice头部。这种表示方法使slice操作和在C中传递指针、长度对一样廉价。

slice相关的函数有如下几个,是不是感觉很熟悉。

func makeslice(et *_type, len64, cap64 int64) slice
func growslice(et *_type, old slice, cap int) slice
func slicecopy(to, fm slice, width uintptr) int
func slicestringcopy(to []byte, fm string) int

slice的扩容

对slice进行append操作时,可能会造成扩容操作。扩容规则如下:

  • 如果新的大小是当前大小2倍以上,则大小增长为新大小
  • 否则循环以下操作:如果当前长度len小于1024,按每次2倍增长,否则每次按当前cap的1/4增长。直到增长的大小超过或等于新大小。
	newcap := old.cap
doublecap := newcap + newcap
//和old.cap的double进行比较
if cap > doublecap {
newcap = cap
} else {
if old.len < 1024 {
newcap = doublecap
} else {
for newcap < cap {
newcap += newcap / 4
}
}
}

slice与unsafe.Pointer相互转换

  1. 利用make+slice弄块内存出来自己管理。。。。这个比较牛逼了
s := make([]byte, 200)
ptr := unsafe.Pointer(&s[0])
  1. 基于内存指针ptr构造出一个slice
var o []byte
sliceHeader := (*reflect.SliceHeader)((unsafe.Pointer(&o)))
sliceHeader.Cap = length
sliceHeader.Len = length
sliceHeader.Data = uintptr(ptr)

new和make

了解完Go对type slice struct的定义之后,再来理解new和make的差异就简单得多了。

  • new(T),仅分配内存,不进行初始化。返回的*T指向一个类型T的零值。
  • make(T, args),分配内存,且进行初始化。返回是T本身。因为T本身就是一个引用类型。

以下属声明的类型为例子,分别用new和make的效果如下图:

type Point struct { X, Y int }
type Rect1 struct { Min, Max Point }
type Rect2 struct { Min, Max *Point }

原文: https://github.com/Kevin-fqh/learning-k8s-source-code/blob/master/%E6%B7%B1%E5%85%A5go/(01)%E5%9F%BA%E6%9C%AC%E7%B1%BB%E5%9E%8B.md

Go语言 基本类型的更多相关文章

  1. 生成跨语言的类型声明和接口绑定的工具(Djinni )

    Djinni 是一个用来生成跨语言的类型声明和接口绑定的工具,主要用于 C++ 和 Java 以及 Objective-C 间的互通. 示例接口定义文件: # Multi-line comments ...

  2. C语言指针类型 强制转换

    关于C语言指针类型 强制转换  引用一篇文章: C语言中,任何一个变量都必须占有一个地址,而这个地址空间内的0-1代码就是这个变量的值.不同的数据类型占有的空间大小不一,但是他们都必须有个地址,而这个 ...

  3. 如何用一个语句判断一个整数是不是二的整数次幂——从一道简单的面试题浅谈C语言的类型提升(type promotion)

    最近招聘季,看JULY大哥的面试100题时,碰到这么一个扩展问题: 如何用一个语句判断一个整数是不是二的整数次幂?(此题在编程之美也有) easy, 2的整数次幂的二进制形式只有一个1,只要用i和i- ...

  4. c语言的类型、运算符与表达式

    title: 2017-10-17c语言的类型.运算符与表达式 tags: c程序设计语言 grammar_cjkRuby: true --- 1.1 数据类型 char 字符型,一个字节 int 整 ...

  5. 3. Go语言基本类型

    Go语言基本类型如下: bool string 数值类型 (int8, int16, int32, int64, int, uint8, uint16, uint32, uint64, uint, f ...

  6. [编程] C语言枚举类型(Enum)

    C语言枚举类型(Enum):定义形式为:enum typeName{ valueName1, valueName2, valueName3, ...... };enum 类型名{名字1,名字2} 枚举 ...

  7. Swift 语言附注 类型

    本页包括内容: 类型注解(Type Annotation) 类型标识符(Type Identifier) 元组类型(Tuple Type) 函数类型(Function Type) 数组类型(Array ...

  8. 学习Golang语言(6):类型--切片

    学习Golang语言(1): Hello World 学习Golang语言(2): 变量 学习Golang语言(3):类型--布尔型和数值类型 学习Golang语言(4):类型--字符串 学习Gola ...

  9. C语言-整数类型

    C语言-整数类型 整数类型 Reg为寄存器 字长,是说这个寄存器是多少宽的,每个寄存器可以表示32bit数据,也是说CPU与RAM每一次传递的数据也是32bit 计算机内部一切都是二进制 所有的类型, ...

  10. C语言-字符类型

    C语言-字符类型 char不仅是一种整数,也是一种特殊的类型:字符(character). 常用单引号表示字符的字面量,如'a', '1'. 单引号''也是一个字符,printf和scanf里用的%c ...

随机推荐

  1. mount -o remount,rw / (这是个求命的命令)

    当系统无法启动的时候.我们会前进入单用户模式(正常情况下单用户莫式是权限是正常的,只在在无法启动的情况下, 再进入单用户模式,权限才会是只读),这时候没有对文件的修改权限(所有的文件都是只读) 用这条 ...

  2. hdu1142(dj+记忆化搜索)

    题意:给你n各点,m行关于这些点的联通关系,以及距离,求从1这个点到2这个点之间,下一个点到2这个点比当前点到2这个点的距离要小的路径的条数...... 思路:dj+记忆化搜索....... #inc ...

  3. (转载)C++STL中vector容器的用法

     vector是C++标准模板库中的部分内容,它是一个多功能的,能够操作多种数据结构和算法的模板类和函数库.vector之所以被认为是一个容器,是因为它能够像容器一样存放各种类型的对象,简单地说vec ...

  4. strcmp在CTF中的案例

    当strcmp比较出错的时候就会为null.null即为0故输出flag. strcmp(arr,str); ?test[]=1 <?php define('FLAG', 'pwnhub{THI ...

  5. Unix系统编程()信号类型和默认行为

    信号类型和默认行为 就是讲了有多少个信号类型 好多啊,后面用到了再看...

  6. telnet 登陆的方法

    第一种方式:通过inetd启动telnetd服务 必须这样设置busybox配置    Networking Utilities --->        去掉 [ ]   Support sta ...

  7. PHP——内测:新闻管理练习题及答案(自己做的)

    试题看文件:1.28练习内测:新闻管理.pdf 数据库为newssystem 表为news 表内容为 fabuxinwen.php <!DOCTYPE html PUBLIC "-// ...

  8. CSS(四):字体和文本属性

    一.字体属性 属性 描述 font-style 设置字体风格 font-weight 设置字体粗细 font-size 设置字体的尺寸(一般用px表示) font-family 设置字体系列 font ...

  9. Python之两个列表一起打乱

    例子: import random c = list(zip(a, b)) random.shuffle(c) a[:], b[:] = zip(*c)

  10. ubuntu vnc安装

    VNC(Virtual Network Computing),为一种使用RFB协议的屏幕画面分享及远程操作软件.此软件借由网络,可发送键盘与鼠标的动作及即时的屏幕画面. 1. 安装vnc服务器 sud ...