golang之data type

目录

1  什么是type system

2  golang data type

2.1  Basic Data Types

2.1.1  Integer

2.1.2  Floats

2.1.3  Complex numbers

2.1.4  byte

2.1.5  rune

2.1.6  strings

2.2  Composite Data Types

2.2.1  Array

2.2.2  Structures

2.2.3  Slice


1  什么是type system

在阅读golang doc的时候,看到这样一段关于golang的描述

It's a fast, statically typed, compiled language that feels like a dynamically typed,interpreted language

由此搜索,引申出来几个概念:statically typed compiled language, dynamically typed,interpreted language等type system相关的概念,几乎每一种开发语言(除了汇编语言)都有自己的一套data type system,没有data type system,计算机就不知道怎么表示程序中的数据,也不知道该如何储存这些数据,以及将两种不同type的数据求和该如何操作,把一个变量定义为整型,则计算机就会知道需要多少字节的内存来表示这个变量,更为重要的是,知道针对这个变量可以进行哪些运算或者操作目,将两个整型数据进行求和和将两个字符串求和是不同的,计算机只有知道了这个数据的类型才会知道该如何处理这个数据,由此可见我们在学习一门新的语言时候,了解该语言的type system也是至关重要的阶段,

Wikipedia上有这样一段介绍 data type system的

In programming languages, a type system is a collection of rules that assign a property called a type to the various constructs—such as variables, expressions, functions or modules—a computer program is composed of. The main purpose of a type system is to reduce bugs in computer programs by defining interfaces between different parts of a computer program, and then checking that the parts have been connected in a consistent way. This checking can happen statically (at compile time), dynamically (at run time), or it can happen as a combination of static and dynamic checking.

通过Wikipedia的介绍我们可以提取些信息:

  1. type system就是一些规则的集合;
  2. 这些规则的check 可以应用在不同阶段,编译阶段或者运行阶段,如果应用在编译阶段则称为编译型语言,如果应用在run time阶段,则称之为解释型语言
  • Strongly typed - many rules
  • Weakly typed - few rules
  • Dynamically typed - rules applied at run time,types are checked at run time
  • Statically typed - rules applied at compile time,types are checked at compile time

Go is a statically typed language,根据上面的描述即可得知 golang的变量类型校验发生在编译阶段。a type system is a collection of rules,这些rules都包括哪些呢:

1、变量的在内存中是如何存储的

2、变量可能赋值的范围

3、可以针对该变量进行的操作目(Operations)

4、其他编译语法的校验

2  golang data type

golang data type分为两类:

  • Basic Data Types
  • Composite Data Types

2.1  Basic Data Types

Built-in Basic Types

builtin package - builtin - Go Packages(The builtin package serves as documentation only. The package does not contain implementations of the functions)

包括:string, bool, float32, float64, complex64, complex128, uint8(byte), uint16, uint32, uint64, int8, int16, int32(rune), int64, int,共计17种类型​​

2.1.1  Integer

整型类型包含了有符号类型和无符号类型两种(signed and unsigned integers)

  • 无符号整型(Unsigned integers)– 包括0在内所有的正数, 包括有uint8, uint16, uint32, uint64
  • 有符号整型(Signed integers) – Signed integers have both positive and negative type integers, and their types include int8, int16, int32, int6

其中8,16,32,64表示每种类型内存中所占的位数,还有三种整型所占内存大小依赖于系统平台 uint, int, and uintptr​

golang Data type data type所占内存大小 data type的取值范围
int/uint 32bits或者64bits(依赖于机器平台) 依赖于机器平台
       int8/uint8         8 bits(1 bytes)

int8         -2^7 to 2^7-1

uint8           0 to 2^8-1

int16/uint16 16bits (2 bytes)

  int16      -2^{15} to 2^{15}-1

uint16       0 to 2^{16}-1

int32/uint32 32bits (4 bytes)

   int32      -2^{31} to 2^{31}-1

uint32      0 to 2^{32}-1

int64/uint64 64bits (8 bytes)

int64   -2^{63} to 2^{63}-1

               uint64     0 to 2^{64}-1               

特别说明一下:int and uint 这两种类型的数据所占内存的大小依赖于平台或者机器,在32位的系统上,int/uint所占内存大小则为32位(4字节),在64位系统上,int/uint所占内存大小则为64位(8字节),我们可以通过reflect包里的TypeOf函数来判断变量的类型、通过unsafe包里的SizeOf函数来获取变量占的内存大小,通过math包里来判断数据类型的取值范围。

2.1.2  Floats

Type Size
float32 32 bits or 4 bytes
float64 64 bits or 8 bytes

float64是默认的float type,当你用双精度的值初始化变量的时候,如果没有特别指明float32或者float64,则默认会使用float64

package main

import (
	"fmt"
	"math"
	"reflect"
	"unsafe"
)

func main() {

	var i int
	var ui uint

	var i8 int8
	var ui8 uint8

	var i16 int16
	var ui16 uint16

	var i32 int32
	var ui32 uint32

	var i64 int64
	var ui64 uint64

	var f32 float32
	var f64 float64

	fmt.Printf("%s default value %d,occupy %d bytes and range %v~%v\n", reflect.TypeOf(i), i, unsafe.Sizeof(i), math.MinInt, math.MaxInt)
	fmt.Printf("%s occupy %d bytes and range %v~%v\n", reflect.TypeOf(ui), unsafe.Sizeof(ui), 0, uint(math.MaxUint))

	fmt.Printf("%s occupy %d bytes and range %v~%v\n", reflect.TypeOf(i8), unsafe.Sizeof(i8), math.MinInt8, math.MaxInt8)
	fmt.Printf("%s occupy %d bytes and range %v~%v\n", reflect.TypeOf(ui8), unsafe.Sizeof(ui8), 0, math.MaxUint8)

	fmt.Printf("%s occupy %d bytes and range %v~%v\n", reflect.TypeOf(i16), unsafe.Sizeof(i16), math.MinInt16, math.MaxInt16)
	fmt.Printf("%s occupy %d bytes and range %v~%v\n", reflect.TypeOf(ui16), unsafe.Sizeof(ui16), 0, math.MaxUint16)

	fmt.Printf("%s occupy %d bytes and range %v~%v\n", reflect.TypeOf(i32), unsafe.Sizeof(i32), math.MinInt32, math.MaxInt32)
	fmt.Printf("%s occupy %d bytes and range %v~%v\n", reflect.TypeOf(ui32), unsafe.Sizeof(ui32), 0, math.MaxUint32)

	fmt.Printf("%s occupy %d bytes and range %v~%v\n", reflect.TypeOf(i64), unsafe.Sizeof(i64), math.MinInt64, math.MaxInt64)
	fmt.Printf("%s occupy %d bytes and range %v~%v\n", reflect.TypeOf(ui64), unsafe.Sizeof(ui64), 0, uint64(math.MaxUint64))

	fmt.Printf("%s occupy %d bytes and range %v~%v\n", reflect.TypeOf(f32), unsafe.Sizeof(f32), -math.MaxFloat32, math.MaxFloat32)
	fmt.Printf("%s occupy %d bytes and range %v~%v\n", reflect.TypeOf(f64), unsafe.Sizeof(f64), -math.MaxFloat64, math.MaxFloat64)
}

输出:

int default value 0,occupy 8 bytes and range -9223372036854775808~9223372036854775807
uint occupy 8 bytes and range 0~18446744073709551615
int8 occupy 1 bytes and range -128~127
uint8 occupy 1 bytes and range 0~255
int16 occupy 2 bytes and range -32768~32767
uint16 occupy 2 bytes and range 0~65535
int32 occupy 4 bytes and range -2147483648~2147483647
uint32 occupy 4 bytes and range 0~4294967295
int64 occupy 8 bytes and range -9223372036854775808~9223372036854775807
uint64 occupy 8 bytes and range 0~18446744073709551615
float32 occupy 4 bytes and range -3.4028234663852886e+38~3.4028234663852886e+38
float64 occupy 8 bytes and range -1.7976931348623157e+308~1.7976931348623157e+308

2.1.3  Complex numbers

形如a+bi,其中a、b都是浮点型,a作为实部,b作为虚部,i是虚数单位。

complex64和complex128,其中64和128分别表示的占用位数

Data type 所占内存大小 特性
complex64 (4 + 4) 8 bytes(64位) 实部和虚部都是float32
complex128 (8 + 8) 16 bytes (128位) 实部和虚部都是float64

复数的初始化有两种方式:

  • 用complex(a,b)函数:使用时要确保a和b都是同类型,都为float32或者float64
  • 用"c := a + bi",用这种方式初始化,如果没有特别声明即为默认的complex128类型
package main

import (
	"fmt"
	"reflect"
	"unsafe"
)

func main() {

	var com64 complex64
	var com128 complex128

	fmt.Printf("%s occupy %d bytes\n", reflect.TypeOf(com64), unsafe.Sizeof(com64))
	fmt.Printf("%s occupy %d bytes\n", reflect.TypeOf(com128), unsafe.Sizeof(com128))

	var a float32 = 3
	var b float32 = 5
	c := complex(a, b)

	d := 4 + 5i

	fmt.Printf("%g's type is %s,and occupy %d bytes,real part's type is %s,imag part's type is %s\n", c, reflect.TypeOf(c), unsafe.Sizeof(c), reflect.TypeOf(real(c)), reflect.TypeOf(imag(c)))
	fmt.Printf("%g's type is %s,and occupy %d bytes,real part's type is %s,imag part's type is %s\n", d, reflect.TypeOf(d), unsafe.Sizeof(d), reflect.TypeOf(real(d)), reflect.TypeOf(imag(d)))
}

输出:

complex64 occupy 8 bytes
complex128 occupy 16 bytes
(3+5i)'s type is complex64,and occupy 8 bytes,real part's type is float32,imag part's type is float32
(4+5i)'s type is complex128,and occupy 16 bytes,real part's type is float64,imag part's type is float64

2.1.4  byte

byte 是个别名类型,是uint8的别名,这意味着byte是整型,占8位(1  byte)的内存,用来表示ASSIC字符,取值范围在0 to 255。(注意区分rune,rune is an alias for int32,The default type for character values is rune,也就是说当我们隐式用一个字符声明变量时,其实我们声明了一个rune类型的变量)

注意区分下面两种情况:

  • var b byte = 'a'    //byte
  • c := 'a'                  //int32
package main

import (
	"fmt"
	"reflect"
	"unsafe"
)

func main() {
	var b byte = 'a' //byte
	c := 'a'         //int32
	fmt.Printf("%d's type is %s,and occupy %d bytes\n", b, reflect.TypeOf(b), unsafe.Sizeof(b))
	fmt.Printf("%d's type is %s,and occupy %d bytes\n", c, reflect.TypeOf(c), unsafe.Sizeof(c))
}

输出:

97's type is uint8,and occupy 1 bytes
97's type is int32,and occupy 4 bytes

2.1.5  rune

rune也是个别名类型,是int32的别名,这意味着rune是一个整型,一个rune类型的值即可表示一个Unicode字符,rune主要用来存储Unicode码点值,Unicode是包含ASSIC在内的更高级的字符集,可以表示世界范围内的绝大部分字符的编码规范,包括汉字,日文,韩文的编码。几乎每一个字符都可以用一个Unicode number来表示,这个Unicode number称之为Unicode码点, 用于代表Unicode字符的编码值也被称为Unicode码点。一个Unicode码点通常由“U+”和一个以十六进制表示法表示的整数表示。例如,英文字母“A”的Unicode码点为“U+0041”

unicode编码我们又可以叫做是统一码。在计算机科学领域中是一中业界标准,unicode编码还包含了字符集、编码方案等等。unicode编码给每个字符提供了一个唯一的数字,不论是什么平台、不论是什么程序、不论是什么语言。unicode编码的出现是为力更好的解决传统字符在编码产生的冲突问题。并且unicode编码给每种语言中的每个字符设定了统一并且唯一的二进制编码

UTF-8 是一种 Unicode 字符编码方法。这意味着 UTF-8 获取给定 Unicode 字符的码位,并将其转换为二进制字符串。它也执行相反操作,以二进制数字读取并将它们转换回字符

Character Code point UTF-8 binary encoding
A U+0041 01000001
a U+0061 01100001
0 U+0030 00110000
9 U+0039 00111001
! U+0021 00100001
Ø U+00D8 11000011 10011000
U+0683 11011010 10000011
U+0C9A 11100000 10110010 10011010
U+2070E 11110000 10100000 10011100 10001110
U+1F601 11110000 10011111 10011000 10000001
package main

import (
	"fmt"
	"reflect"
	"unsafe"
)

func main() {
	r := 'a'

	//Print Size
	fmt.Printf("Size: %d\n", unsafe.Sizeof(r))

	//Print Type
	fmt.Printf("Type: %s\n", reflect.TypeOf(r))

	//Print Code Point
	fmt.Printf("Unicode CodePoint: %U\n", r)

	//Print Character
	fmt.Printf("Character: %c\n", r)
	s := "0b£"

	//This will print the Unicode Points
	fmt.Printf("%U\n", []rune(s))

	//This will the decimal value of Unicode Code Point
	fmt.Println([]rune(s))
}

输出:

Size: 4
Type: int32
Unicode CodePoint: U+0061
Character: a
[U+0030 U+0062 U+00A3]
[48 98 163]

2.1.6  strings

golang的strings本质就是只读的字符数组,golang 中的字符串统一使用 UTF-8 (属于Unicode编码的一种实现方式)进行编码,golang中字符或者字符串初始化的时候常常用三种引号来包含:

  • 单引号(’’):single quote,常用来限定byte类型和rune类型,默认是rune类型,
  • 双引号(""):Double quotes,用来限定strings类型,
  • 反引号(``):Back quotes,(标准键盘上Esc下面的那个键),用来限定raw string,即原始字符串,你输入什么样就按什么样输出,不支持转义字符,所有转义字符会按字面量输出,如`\n`则会输出\n.
package main

import (
	"fmt"
	"reflect"
	"unsafe"
)

func main() {
	//String in double quotes
	str1 := "hello \nworld"
	fmt.Printf("str1 is: %s\n", str1)

	fmt.Printf("str1's type is %s,and occup %d bytes\n", reflect.TypeOf(str1), unsafe.Sizeof(str1))

	str2 := "hello\\nworld"
	fmt.Printf("str2 is: %s\n", str2)

	//String in back quotes
	str3 := `hello\nworld`
	fmt.Printf("str3 is: %s\n", str3)

	str4 := `hello
		world`

	fmt.Printf("str4 is: %s\n", str4)

	str5 := "hello world"
	//This will print the byte sequence.
	//Since character a and b occupies 1 byte each and £ character occupies 2 bytes.
	//The final output will 4 bytes
	fmt.Println([]byte(str5))

	fmt.Println([]rune(str5))

	//string from a slice of bytes
	sliceStr := []byte{104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100}
	fmt.Printf("sliceStr is: %s\n", string(sliceStr))

	runeStr := []rune{104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100}
	fmt.Printf("runeStr is: %s\n", string(runeStr))
}

输出:

str1 is: hello 
world
str1's type is string,and occup 16 bytes
str2 is: hello\nworld
str3 is: hello\nworld
str4 is: hello
		world
[104 101 108 108 111 32 119 111 114 108 100]
[104 101 108 108 111 32 119 111 114 108 100]
sliceStr is: hello world
runeStr is: hello world

2.1.7  Booleans

布尔类型只有两个值,true和false,默认值为false

针对布尔类型的操作目只有:与:&&、或:||、非: !

package main

import (
	"fmt"
	"reflect"
	"unsafe"
)

func main() {
	var i bool

	// to print the value of the variable
	fmt.Printf("Value of i:%t\n", i)

	// to print the data type of the variable
	fmt.Printf("i's type is :%s,and occupy %d bytes\n", reflect.TypeOf(i), unsafe.Sizeof(i))
}

输出:

Value of i:false
i's type is :bool,and occupy 1 bytes

2.2  Composite Data Types

复合类型是由各种basic type,像int,string,booleans组合而成的类型

包括:pointer, function, interface, struct, map, slice, array, channel。共计8种类型。

  • pointer type:类似C语言指针
  • struct type:类似C语言struct
  • function type- 函数类型在golang里是first-class type,就是可以像int变量一样可以赋给一个变量,或者传参给其他function的类型。
  • array和struct都是声明后固定size的类型,而slices和map是声明后可以动态伸缩大小的类型

分了三类:

  • Non-Reference Types ( like  Array struct)
  • Reference Types ( like ,slice map , etc. )
  • Interface

2.2.1  Array

array是固定长度,由0个或者多个其他同类型组成的集合。在使用array的时候一个很容易犯的错误就是越界问题,这个在go编译器给了很好的提示:一般两种越界提示

index must be no-negative

out of bound for 2-element array

golang在使用的时候有些短板,从而开发的时候总会摒弃array而选择slices

array的短板:

  1. 一旦你定义了一个数组,是不允许更改其size的,这就意味,数组不是动态的,如果你想向一个没有剩余空间的array添加元素,你需要重新创建一个更大的array,然后把所有的元素拷贝到这个新的array里,然后再把要添加的元素添加到这个新的array的末尾
  2. 当你想把一个array作为参数传递给某个函数的时候,你实际上是传递只是这个array的副本,这就导致,你在函数里对这个array做的任何修改,在函数退出后,所有的修改都会丢失,
  3. 向一个函数传递一个大size的array的时候,由于传递的是这个array的副本,会导致内存空间的占用和运行速度的大打折扣

而golang提供了一个解决上述问题的数据类型slice,这个在下一段介绍

array声明:

用具体的value赋值

newArray := [n]Type{val1, val2, val3}

不用具体的value赋值,默认用0值初始化

newArray := [len]Type{}

array是固定长度的理解,也就是说,编译器是不允许将同类型,但不同长度的数组进行赋值的 

当我们将array作为参数传递给一个函数时,array的length作为了参数的一部分传递给了这个函数,eg:

func change(a [3]int)

package main

import (
	"fmt"
	"reflect"
)

func change(a [3]int) {
	a[1] = 2
	fmt.Println("the array in function is:", a)
}

func main() {
	var array1 [3]int = [3]int{100, 200, 300}

	fmt.Printf("the array1's type is %s and length is:%d\n", reflect.TypeOf(array1), len(array1))

	fmt.Println("before change array is:", array1)

	change(array1)

	fmt.Println("after change array is:", array1)
}

输出:

the array1's type is [3]int and length is:3
before change array is: [100 200 300]
the array in function is: [100 2 300]
after change array is: [100 200 300]

2.2.2  Structures

golang已经有了array,slice,maps,并且已经很灵活,用处广泛,但是这些都有一个共同的缺点就是只能存储同一type的数据,不能把多个不同type的数据放到一块,当我们需要开发者自定义地把不同type的数据当作一个数据单元来处理的时候,就需要用到structures(struct)了,这个组成structures的不同类型得数据,我们称为这个structures的域。

  1. 怎样创建structures

我们可以用struct关键词来声明一个struct,具体方式struct后跟一对大括号,括号里是用户自定义的一个或者多个域和域的类型

struct {

   field1 field1_DataType

   field2 field2_DataType

}

我们也可以创建用户自定义的struct类型,用这个类型的struct来声明一个struct变量,具体形式如

type type_name struct {

   field1 field1_DataType

   field2 field2_DataType

}

如果想创建一个自定义的struct的数据类型,如:

type Person struct {

    Name string

    age       int

    height    float64

    weight    float64

}

我们可以用新创建的Person struct来声明一个变量,如:

var per Person

package main

import (
	"fmt"
)

type Person struct {
	name   string
	age    int
	height float64
	weight float64
}

type Student struct {
	string
	int
}

func main() {

	// create named struct
	var per1 Person

	per1.name = "sam"
	per1.age = 18
	per1.height = 183.5
	per1.weight = 145.5

	fmt.Println("per1's age:", per1.age)
	per1.age = 45

	fmt.Println("change per1's age:", per1.age)

	//create named struct
	per2 := Person{name: "Tom", age: 20, height: 185, weight: 150.5}
	fmt.Println("per's name:", per2.name)

	//Pointers to a struct
	pPer3 := &Person{
		name:   "lily",
		age:    22,
		height: 168,
		weight: 112.5,
	}

	fmt.Println("Per3's name", (*pPer3).name)

	//create anonymous structs
	teacher := struct {
		name   string
		age    int
		salary int
	}{
		name:   "Wang",
		age:    40,
		salary: 8000,
	}

	fmt.Println("teacher's name:", teacher.name)

	//anonymous fields
	stu := Student{"LiGang", 27}
	fmt.Println("stu:", stu)

	//use new keyword, returns the pointer to the newly allocated struct
	per4 := new(Person)
	per4.name = "Lucy"
	per4.age = 28

	fmt.Println("per4", per4)

}

输出:

per1's age: 18
change per1's age: 45
per's name: Tom
Per3's name lily
teacher's name: Wang
stu: {LiGang 27}
per4 &{Lucy 28 0 0}

2.2.3  Slice

前面谈到了array,但是array有一个很主要的缺陷就是大小是固定的,同时函数传参也是按值传递,多了一份拷贝,而golang提供了另一个数据类型slice,与array类似,但是其长度大小可以很好地伸缩,且是引用传参,这就是说,当slice作为参数传递给函数时,其实传递的是这个slice的地址,函数内部对这个slice的任何修改也不会丢失,同时当传递给函数一个比较大的slice时候,引用传递,相比较array,也很好的利用了空间,效率也有很大的提升,slice的底层实现其实是按动态数组按引用方式使用的。

slice的内部是通过一个strcuct表示的:

Slices: The slice header

Slices are where the action is, but to use them well one must understand exactly what they are and what they do.

A slice is a data structure describing a contiguous section of an array stored separately from the slice variable itself. A slice is not an array. A slice describes a piece of an array.

type SliceHeader strcut {

        Pointer uintptr

        Len       int

        Cap      int

}

  • Pointer to the underlying array
  • Current length of the underlying array
  • Total Capacity which is the maximum capacity to which the underlying array can expand

slice的声明:注意区分array的声明,slice的声明没有指明element的个数,T是golang的data type

array声明:var array [10]T

slice声明:var slice []T

slice的创建

这里有五种方式创建slice:

(1)用 []<type>{}的形式创建

s := []int{}      //创建了一个length为0和capacity为0的slice

s := []int{1,2} //初始化的时候创建,创建了一个length为2,capacity为2的slice

(2)从一个array创建slice

var num = [6]int{1,2,3,4,5,6}

sliceNum = num[1:5]

(3)从一个slice创建slice

var slice1 =  []int{ 1, 3, 5, 7, 9, 11, 13, 15}

slice2 := slice1[1:5]

(4)用make函数创建slice

func make([]T, len, cap) []T

其中的cap参数是可选项并且默认等于len,make函数创建了一个size为cap的底层array,并且返回一个指向指向这个array的slice

// declaration and initialization

var numbers = make([]int, 5, 10)

// or

// short variable declaration

numbers2 := make([]int, 5, 10)

package main

import "fmt"

func main() {
	// Creates an array of size 10, slices it till index 5, and returns the slice reference
	s := make([]int, 5, 10)
	fmt.Printf("s = %v, len = %d, cap = %d\n", s, len(s), cap(s))
}

 输出:

s = [0 0 0 0 0], len = 5, cap = 10

(5)用new函数创建slice

num := new([]int)

slice相关的几个函数

Functions

Descriptions

append()

adds element to a slice

copy()

copy elements of one slice to another

Equal()

compares two slices

len()

find the length of a slice

package main

import "fmt"

func main() {

	//create slice with literal syntax
	slice1 := []int{}
	fmt.Printf("slice1=%v,  length=%d,  capacity=%d\n", slice1, len(slice1), cap(slice1))

	var slice2 = []int{1, 2, 3, 4, 5, 6}
	fmt.Printf("slice2=%v,  length:%d,  ccapacity=%d\n", slice2, len(slice2), cap(slice2))

	//create slice from array
	var num = [6]int{1, 2, 3, 4, 5, 6}
	sliceNum := num[1:5]
	fmt.Printf("sliceNum=%v,  length=%d,  capacity=%d\n", sliceNum, len(sliceNum), cap(sliceNum))

	//create slice from another slice
	slice3 := sliceNum[2:4]
	fmt.Printf("slice3=%v, length=%d, capacity=%d\n", slice3, len(slice3), cap(slice3))

	// creates an array of size 10, slices it till index 5, and returns the slice reference
	slice4 := make([]int, 5, 10)
	fmt.Printf("slice4=%v, length=%d, capacity=%d\n", slice4, len(slice4), cap(slice4))

	//modify value in slice
	slice2[2] = 30
	fmt.Printf("slice2=%v,  length:%d,  ccapacity=%d\n", slice2, len(slice2), cap(slice2))

	//iteration over a slice
	for i, v := range slice2 {
		fmt.Println(i, v)
	}

	//append new elements to slice
	slice2 = append(slice2, 30, 40, 50)
	fmt.Printf("slice2=%v,  length:%d,  ccapacity=%d\n", slice2, len(slice2), cap(slice2))

	var slice5 = make([]int, 5)
	_ = copy(slice5, slice2)

	//fmt.Println(slice6)
	fmt.Printf("slice5=%v,  length:%d,  ccapacity=%d\n", slice5, len(slice5), cap(slice5))

}

输出:

slice1=[],  length=0,  capacity=0
slice2=[1 2 3 4 5 6],  length:6,  ccapacity=6
sliceNum=[2 3 4 5],  length=4,  capacity=5
slice3=[4 5], length=2, capacity=3
slice4=[0 0 0 0 0], length=5, capacity=10
slice2=[1 2 30 4 5 6],  length:6,  ccapacity=6
0 1
1 2
2 30
3 4
4 5
5 6
slice2=[1 2 30 4 5 6 30 40 50],  length:9,  ccapacity=12
slice5=[1 2 30 4 5],  length:5,  ccapacity=5

猜你喜欢

转载自blog.csdn.net/u011285281/article/details/128204809