Last article details the Go
basis of language, pointed Go
and differences other mainstream programming languages, more focused on the details of grammar, I believe that with a little memory can easily switch from an existing programming language to Go
programming language customary in , although the switch may not be particularly smooth, but especially a lot of trial and error practice more, always can slowly feel the Go
beauty of the language!
In the study Go
before the built-in container, the same, we briefly review the Go
basic language, with knowledge of the new temperature can serve as a teacher!
Review section on knowledge
For more information, please micro-channel public number [Snow Dream Inn technology] to see inside go study notes the particular concern of what basic grammar article, feel useful, easily forwarded chant!
Built-in type species
bool
Boolean, optional
true|false
, the default value of zero initializationfalse
.
(u)int
,(u)int8
,(u)int16
,(u)int32
,(u)int64
,uintptr
2^0=1
,2^1=2
,2^2=4
A byte integer length, and comprising a signed integer, and unsigned integeruintptr
type of pointer type, the default value is initialized to zero0
.
byte(uint8)
,rune(int32)
,string
byte
It is the most basic byte type is theuint8
type of alias , andrune
isGo
the character type, isint32
an alias. The most common type stringstring
should not have introduced it?
float32
,float64
,complex64
,complex128
Only
float
type float, nodouble
type, to distinguish the same length in bytes,complex64
it is a complex type, the real and imaginary parts of afloat32
complex type made, thus writingcomplex64
this form.
Features built-in type
- Only display conversion type conversion, there is no form of implicit type conversions
Not automatically implicit type conversions between different types of variable
Go
type conversion is only mandatory language, can only display conversion.
- While providing the type of pointer, but the pointer itself can not carry out any form of computing.
Pointer type variables can not be calculated, but can be re-directed to change the memory address.
- After the declaration of a variable is initialized with a default value of zero, zero value variable depending on the specific on the type of
int
Zero value type of a variable is initialized0
,string
zero value type is initialized to an empty string, notnil
Basic operators
- No arithmetic operators
++i
and--i
Only
i++
, andi--
this increment operator, no longer have to worry about the differences of the two ways!
- Comparison operators
==
can compare arrays for equality
When the values of the array length and dimensions of the two arrays, two arrays can be compared, when exactly the same order, as a result
true
, otherwise it isfalse
.
- Bitwise Operators Bitwise new operator clears
&^
Other mainstream programming language, although there is no such operator, the command can also be achieved by combining similar functions, but since it provides a bit is cleared by the operator, no longer have to conduct their own combination using!
Flow control statements
if
The conditional expression does not need parentheses and support for variable assignment
Define temporary variables and variable according to the logic, then classification process according to different situations,
Go
handling of such temporary variables, conditional expressions directly enhanced, this situation will be very common in the future!
if
Variables defined in the conditional expression scope is limited to the current statement block
Variables defined in the conditional expression is to facilitate the different branches of the processing logic, since it is a temporary variable, a current
if
block of statements can not be used, it becomes possible to understand.
switch
Statement can notbreak
, unless thefallthrough
switch
Multiple statementscase
at the end can notbreak
, the system will automaticallybreak
process.
switch
The conditional expression is not limited to a constant integer or
And compared to other mainstream programming language,
Go
the language ofswitch
the conditional expression is more powerful, but also more relaxed type.
switch
The conditional expression may be omitted, the steering branching logiccase
language.
Omitting
switch
the conditional expression, a plurality ofcase
language branching process control, multi-function and effectif else
the same.
- Omitting
switch
the conditional expression, for eachcase
condition may have multiple conditions, separated by commas.
swicth
The statement is essentially the corresponding flow control according to different conditions, eachcase
conditional expression to support multiple, but also enhances the ability of process control.
for
Conditional expressions cycle does not need parentheses, and no other form of circulation.
Go
Language onlyfor
cycle, nowhile
other form of circulation.
for
The initial condition for the loop termination condition expressions, and self-energizing may be omitted while omitting or
After the conditional expression can be omitted to achieve
while
the effect of the cycle, all omitted, is an endless loop.
Function and parameter passing
- Function declaration in accordance with the function name, into the reference, the reference sequence is defined, and supports multiple return values
Whether variable definition or function definition,
Go
always and other mainstream programming language to the opposite of, if I can think of in the order of input and output will find that this definition is actually quite justified way.
- Function has multiple return values can be named to the return value, but there is no difference in terms of the caller
You may have a function return multiple values variable names to facilitate the call to quickly see the familiar function declaration name known meaning, but the caller does not have to call to receive the return value in accordance with the result of the name.
- Into the reference function is not complicated concepts required parameters, optional parameters, only supports variable argument lists
Variable parameter lists and other mainstream programming languages, must be the last one into the argument.
- Passing arguments to functions only transfer value, no reference is transmitted, i.e., all variables need to copy
Only the parameter values are passed passed, more simple logic, but can be passed to achieve the effect of passing a pointer references dealing with complex situations.
What are built container
Reviewed Go
the basic grammar of the language, we began to continue learning variable type of knowledge that is the bearer of the container.
Carrying a class of the most basic underlying variable is an array of containers, the most senior of the container bottom can rely array package, we first look at Go
the array What is the difference?
Arrays and slices
- Declare and initialize an array
Distinctive features of the array is at the same time the length of the statement of contiguous memory a set of specific length, when declaring an array must specify the array can be initialized, of course, when you do not specify the array length can also use the ...
syntax for the compiler to help us determine the length of the array.
func TestArray(t *testing.T) {
var arr1 [3]int
arr2 := [5]int{1, 2, 3, 4, 5}
arr3 := [...]int{2, 4, 6, 8, 10}
// [0 0 0] [1 2 3 4 5] [2 4 6 8 10]
t.Log(arr1, arr2, arr3)
var grid [3][4]int
// [[0 0 0 0] [0 0 0 0] [0 0 0 0]]
t.Log(grid)
}
[3]int
Specified array length3
, element typeint
, of course, can also directly assign declaration[5]int{1, 2, 3, 4, 5}
, if bother specified array length, it can be[...]int{2, 4, 6, 8, 10}
expressed.
- And traverse the elements of the array access
The most common for
loop traverse is accessed according to the index of the array, range arr
the way provides a convenient way to simplify traversal.
func TestArrayTraverse(t *testing.T) {
arr := [...]int{2, 4, 6, 8, 10}
for i := 0; i < len(arr); i++ {
t.Log(arr[i])
}
for i := range arr {
t.Log(arr[i])
}
for i, v := range arr {
t.Log(i, v)
}
for _, v := range arr {
t.Log(v)
}
}
range arr
Can return to the index value and the index entries, if only care about the index entry and do not care about the value of the index, you can use_
placeholder represents the index value is ignored, if only care about the value of the index, you can not write index entry. This is the function of the processing logic multi sequentially receives the return value, unused variables may not appear.
- Array is a value type can be compared
An array is a value type, this and other mainstream programming languages are different, so the same latitude and same number of elements in the array can be compared, in front of the contents in this regard has also been emphasized here again briefly recall.
func printArray(arr [5]int) {
arr[0] = 666
for i, v := range arr {
fmt.Println(i, v)
}
}
func TestPrintArray(t *testing.T) {
var arr1 [3]int
arr2 := [5]int{1, 2, 3, 4, 5}
arr3 := [...]int{2, 4, 6, 8, 10}
// [0 0 0] [1 2 3 4 5] [2 4 6 8 10]
t.Log(arr1, arr2, arr3)
// cannot use arr1 (type [3]int) as type [5]int in argument to printArray
//printArray(arr1)
fmt.Println("printArray(arr2)")
printArray(arr2)
fmt.Println("printArray(arr3)")
printArray(arr3)
// [1 2 3 4 5] [2 4 6 8 10]
t.Log(arr2, arr3)
}
Because the parameter passed is passed by value, so the
printArray
function can not change the external value of the function caller passed, if you want to function inprintArray
an array of content delivery over internal changes can be achieved through a pointer, but is there a more simple way?
Want to printArrayByPointer
modify the parameter array inside the function, array pointer by the way, if there are not familiar with the place, you can look to see the review article.
func printArrayByPointer(arr *[5]int) {
arr[0] = 666
for i, v := range arr {
fmt.Println(i, v)
}
}
func TestPrintArrayByPointer(t *testing.T) {
var arr1 [3]int
arr2 := [5]int{1, 2, 3, 4, 5}
arr3 := [...]int{2, 4, 6, 8, 10}
// [0 0 0] [1 2 3 4 5] [2 4 6 8 10]
t.Log(arr1, arr2, arr3)
fmt.Println("printArrayByPointer(arr2)")
printArrayByPointer(&arr2)
fmt.Println("printArrayByPointer(arr3)")
printArrayByPointer(&arr3)
// [666 2 3 4 5] [666 4 6 8 10]
t.Log(arr2, arr3)
}
Modify elements of the array may be achieved by passing an array of pointers, in addition,
Go
the language there is a close relative of the arrayslice
, i.e. the slice, it can achieve a similar effect.
- Slice the declaration and initialization
Slice and arrays are very similar, if not the length of the array is created when the array is specified, then the final slice is not actually created an array.
func TestSliceInit(t *testing.T) {
var s1 [5]int
// [0 0 0 0 0]
t.Log(s1)
var s2 []int
// []
t.Log(s2,len(s2))
}
[]int
Length is not specified, this time slice is created, the default value of zero initialization isnil
not empty array!
Similarly, you can declare and initialize an array, can be sliced, and the syntax is very similar, little attention thought it was an array of it!
func TestSliceInitValue(t *testing.T) {
var s1 = [5]int{1, 3, 5, 7, 9}
// [1 3 5 7 9]
t.Log(s1)
var s2 = []int{1, 3, 5, 7, 9}
// [1 3 5 7 9]
t.Log(s2)
}
Just do not specify the
[]
length, the final result was created to become a slice, really dazzling!
Arrays and slices so similar, people have suspected what shady dealings between the two can actually get a slice from an array, the following are examples?:
func TestSliceFromArray(t *testing.T) {
arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
// arr = [0 1 2 3 4 5 6 7 8 9]
t.Log("arr = ", arr)
// arr[2:6] = [2 3 4 5]
t.Log("arr[2:6] = ", arr[2:6])
// arr[:6] = [0 1 2 3 4 5]
t.Log("arr[:6] = ", arr[:6])
// arr[2:] = [2 3 4 5 6 7 8 9]
t.Log("arr[2:] = ", arr[2:])
// arr[:] = [0 1 2 3 4 5 6 7 8 9]
t.Log("arr[:] = ", arr[:])
}
arr[start:end]
The results obtained by the interception of a part of the array is the slice, slice concept is very vivid ah!
And other mainstream programming languages, [start:end]
is a closed left and right open interval, sliced meaning is very clear:
Ignore the starting index start
, the arr[:end]
representation from the beginning until the termination of the original array index end
before one;
ignored termination index end
, the arr[ start:]
representation from the original array starting index start
start until the last bit;
both ignore the starting index and ignoring the termination of the index, although less common but should be is on the meaning of the original array, but remember that the type is not an array slice yo!
So far, we know that is very similar to an array of slices and slice relative to the size of the array is not only, as it does it on a slice operation and arrays?
func updateSlice(s []int) {
s[0] = 666
}
func TestUpdateSlice(t *testing.T) {
arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
// arr = [0 1 2 3 4 5 6 7 8 9]
t.Log("arr = ", arr)
s1 := arr[2:6]
// s1 = [2 3 4 5]
t.Log("s1 = ", s1)
s2 := arr[:6]
// s2 = [0 1 2 3 4 5]
t.Log("s2 = ", s2)
updateSlice(s1)
// s1 = [666 3 4 5]
t.Log("s1 = ", s1)
// arr = [0 1 666 3 4 5 6 7 8 9]
t.Log("arr = ", arr)
updateSlice(s2)
// s2 = [666 1 666 3 4 5]
t.Log("s2 = ", s2)
// arr = [666 1 666 3 4 5 6 7 8 9]
t.Log("arr = ", arr)
}
Things can actually change the slice to pass parameters, but this is not done array of ah! Unless the array pointer type, slice was able to easily do? Unless it is inside a slice pointer, because the parameters passed only value is passed, there is no way passed by reference !
Slice and array performance parameters passed in a different, specific performance can not be modified when the array is an array parameter passing, you want to pass an array only want to change the array pointer for the job and has achieved a slice of the array change!
Since the parameter values are passed pass only one way, it is presumed that there is certainly inside the slice pointer, parameter passing is passed a pointer, the internal function of changes can affect the function of the external variables.
slice
There are three implementations of internal variables, pointersptr
, the numberlen
and capacitycap
, whichptr
points to the actual data storage addresses.
It is because of this slice internal implementation requires characteristic manifestations worth mentioning Ye Hao makes switches and arrays are inextricably linked, in fact, this data is the result of an extension of static arrays, in essence, is a dynamic array only, but the Go
language is called a slice !
Slice is a dynamic array, it is easy to explain the above problem, the transmission parameter is an internal pointer passed, and thus the value passed though a copy pointer, but the pointer to the real elements, after all, is the same, so that the slice value of the external parameters can be modified .
Arrays can be compared to a certain extent, is a dynamic array slice, can not be compared to? Let the following test methods to verify your guess now!
不知道你有没有猜对呢?切片并不能进行比较,只能与
nil
进行判断.
- 切片的添加和删除
数组是静态结构,数组的大小不能扩容或缩容,这种数据结构并不能满足元素个数不确定场景,因而才出现动态数组这种切片,接下来重点看下切片怎么添加或删除元素.
func printSlice(s []int) {
fmt.Printf("s = %v, len(s) = %d, cap(s) = %d\n", s, len(s), cap(s))
}
func TestSliceAutoLonger(t *testing.T) {
var s []int
// []
t.Log(s)
for i := 0; i < 10; i++ {
s = append(s, i)
printSlice(s)
}
// [0 1 2 3 ...,98,99]
t.Log(s)
for i := 0; i < 10; i++ {
s = s[1:]
printSlice(s)
}
// [0 1 2 3 ...,98,99]
t.Log(s)
}
添加元素
s = append(s, i)
需要扩容时,每次以2
倍进行扩容,删除元素s[1:]
时,递减缩容.
s = append(s, i)
向切片中添加元素并返回新切片,由于切片是动态数组,当切片内部的数组长度不够时会自动扩容以容纳新数组,扩容前后的内部数组会进行元素拷贝过程,所以 append
会返回新的地址,扩容后的地址并不是原来地址,所以需要用变量接收添加后的切片.
当不断进行切片重新截取时 s[1:]
,切片存储的元素开始缩减,个数递减,容量也递减.
其实除了基于数组创建切片和直接创建切片的方式外,还存在第三种创建切片的方式,也是使用比较多的方式,那就是 make
函数.
func TestMakeSlice(t *testing.T) {
s1 := make([]int,10)
// s1 = [0 0 0 0 0 0 0 0 0 0], len(s1) = 10, cap(s1) = 10
t.Logf("s1 = %v, len(s1) = %d, cap(s1) = %d", s1, len(s1), cap(s1))
s2 := make([]int, 10, 32)
// s2 = [0 0 0 0 0 0 0 0 0 0], len(s2) = 10, cap(s2) = 32
t.Logf("s2 = %v, len(s2) = %d, cap(s2) = %d", s2, len(s2), cap(s2))
}
通过 make
方式可以设置初始化长度和容量,这是字面量创建切片所不具备的能力,并且这种方式创建的切片还支持批量拷贝功能!
func TestCopySlice(t *testing.T) {
var s1 = []int{1, 3, 5, 7, 9}
var s2 = make([]int, 10, 32)
copy(s2, s1)
// s2 = [1 3 5 7 9 0 0 0 0 0], len(s2) = 10, cap(s2) = 32
t.Logf("s2 = %v, len(s2) = %d, cap(s2) = %d", s2, len(s2), cap(s2))
var s3 []int
copy(s3, s1)
// s3 = [], len(s3) = 0, cap(s3) = 0
t.Logf("s3 = %v, len(s3) = %d, cap(s3) = %d", s3, len(s3), cap(s3))
}
func copy(dst, src []Type) int
是切片之间拷贝的函数,神奇的是,只有目标切片是make
方式创建的切片才能进行拷贝,不明所以,有了解的小伙伴还请指点一二!
切片的底层结构是动态数组,如果切片是基于数组截取而成,那么此时的切片从效果上来看,切片就是原数组的一个视图,对切片的任何操作都会反映到原数组上,这也是很好理解的.
那如果对切片再次切片呢,或者说切片会不会越界,其实都比较简单了,还是稍微演示一下,重点就是动态数组的底层结构.
func TestSliceOutOfBound(t *testing.T) {
arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
s1 := arr[2:6]
// s1 = [2 3 4 5], len(s1) = 4, cap(s1) = 6
t.Logf("s1 = %v, len(s1) = %d, cap(s1) = %d", s1, len(s1), cap(s1))
s2 := s1[3:5]
// s2 = [5 6], len(s2) = 2, cap(s2) = 3
t.Logf("s2 = %v, len(s2) = %d, cap(s2) = %d", s2, len(s2), cap(s2))
}
[]
只能访问len(arr)
范围内的元素,[:]
只能访问cap(arr)
范围内的元素,一般而言cap >= len
所以某些情况看起来越界,其实并不没有越界,只是二者的标准不同!
我们知道切片 slice
的内部数据结构是基于动态数组,存在三个重要的变量,分别是指针 ptr
,个数 len
和容量 cap
,理解了这三个变量如何实现动态数组就不会掉进切片的坑了!
个数 len
是通过下标访问时的有效范围,超过 len
后会报越界错误,而容量 cap
是往后能看到的最大范围,动态数组的本质也是控制这两个变量实现有效数组的访问.
因为
s1 = [2 3 4 5], len(s1) = 4, cap(s1) = 6
,所以[]
访问切片s1
元素的范围是[0,4)
,因此最大可访问到s1[3]
,而s1[4]
已经越界了!
因为
s1 = [2 3 4 5], len(s1) = 4, cap(s1) = 6
,所以[:]
根据切片s1
创建新切片的范围是[0,6]
,因此最大可访问范围是s1[0:6]
,而s1[3:7]
已经越界!
集合 map
集合是一种键值对组成的数据结构,其他的主流编程语言也有类似概念,相比之下,Go
语言的 map
能装载的数据类型更加多样化.
- 字面量创建
map
换行需保留逗号,
func TestMap(t *testing.T) {
m1 := map[string]string{
"author": "snowdreams1006",
"website": "snowdreams1006",
"language": "golang",
}
// map[name:snowdreams1006 site:https://snowdreams1006.github.io]
t.Log(m1)
}
一对键值对的结尾处加上逗号
,
可以理解,但是最后一个也要有逗号这就让我无法理解了,Why
?
make
创建的map
和字面量创建的map
默认初始化零值不同
func TestMapByMake(t *testing.T) {
// empty map
m1 := make(map[string]int)
// map[] false
t.Log(m1, m1 == nil)
// nil
var m2 map[string]int
// map[] true
t.Log(m2, m2 == nil)
}
make
函数创建的map
是空map
,而通过字面量形式创建的map
是nil
,同样的规律也适合于切片slice
.
range
遍历map
是无序的
func TestMapTraverse(t *testing.T) {
m := map[string]string{
"name": "snowdreams1006",
"site": "https://snowdreams1006.github.io",
}
// map[name:snowdreams1006 site:https://snowdreams1006.github.io]
t.Log(m)
for k, v := range m {
t.Log(k, v)
}
t.Log()
for k := range m {
t.Log(k)
}
t.Log()
for _, v := range m {
t.Log(v)
}
}
这里再一次遇到
range
形式的遍历,忽略键或值时用_
占位,也是和数组,切片的把遍历方式一样,唯一的差别就是map
没有索引,遍历结果也是无序的!
- 获取元素时需判断元素是否存在
func TestMapGetItem(t *testing.T) {
m := map[string]string{
"name": "snowdreams1006",
"site": "https://snowdreams1006.github.io",
}
// snowdreams1006
t.Log(m["name"])
// zero value is empty string
t.Log(m["author"])
// https://snowdreams1006.github.io
if site, ok := m["site"]; ok {
t.Log(site)
} else {
t.Log("key does not exist ")
}
}
Go
语言的map
获取不存在的键时,返回的是值对应类型的零值,map[string]string
返回的默认零值就是空字符串,由于不会报错进行强提醒,这也就要求我们调用时多做一步检查.当键值对存在时,第二个返回值返回true
,不存在时返回false
.
- 删除键值对时用
delete
函数
func TestMapDeleteItem(t *testing.T) {
m := map[string]string{
"name": "snowdreams1006",
"site": "https://snowdreams1006.github.io",
}
// map[name:snowdreams1006 site:https://snowdreams1006.github.io]
t.Log(m)
delete(m, "name")
// map[site:https://snowdreams1006.github.io]
t.Log(m)
delete(m, "id")
// map[site:https://snowdreams1006.github.io]
t.Log(m)
}
delete(map,key)
用于删除map
的键值对,如果想要验证是否删除成功,别忘了使用value,ok := m[k]
确定是否存在指定键值对
- 除
slice
,map
,func
外,其余类型均可键
因为
map
是基于哈希表实现,所以遍历是无序的,另一方面因为slice
,map
,func
不可比较,因为也不能作为键.当然若自定义类型struc
不包含上述类型,也可以作为键,并不要求实现hashcode
和equal
之类的.
value
可以承载函数func
类型
func TestMapWithFunValue(t *testing.T) {
m := map[int]func(op int) int{}
m[1] = func(op int) int {
return op
}
m[2] = func(op int) int {
return op * op
}
m[3] = func(op int) int {
return op * op * op
}
// 1 4 27
t.Log(m[1](1), m[2](2), m[3](3))
}
再一次说明函数是一等公民,这部分会在以后的函数式编程中进行详细介绍.
没有 set
Go
的默认类型竟然没有 set
这种数据结构,这在主流的编程语言中算是特别的存在了!
正如 Go
的循环仅支持 for
循环一样,没有 while
循环一样可以玩出 while
循环的效果,靠的就是增强的 for
能力.
所以,即使没有 set
类型,基于现有的数据结构一样能实现 set
效果,当然直接用 map
就可以封装成 set
.
func TestMapForSet(t *testing.T) {
mySet := map[int]bool{}
mySet[1] = true
n := 3
if mySet[n] {
t.Log("update", mySet[n])
} else {
t.Log("add", mySet[n])
}
delete(mySet, 1)
}
使用
map[type]bool
封装实现set
禁止重复性元素的特性,等到讲解到面向对象部分再好好封装,这里仅仅列出核心结构.
知识点总结梳理
Go
语言是十分简洁的,不论是基础语法还是这一节的内建容器都很好的体现了这一点.
数组作为各个编程语言的基础数据结构,Go
语言和其他主流的编程语言相比没有什么不同,都是一片连续的存储空间,不同之处是数组是值类型,所以也是可以进行比较的.
这并不是新鲜知识,毕竟上一节内容已经详细阐述过该内容,这一节的重点是数组的衍生版切片 slice
.
因为数组本身是特定长度的连续空间,因为是不可变的,其他主流的编程语言中有相应的解决方案,其中就有不少数据结构的底层是基于数组实现的,Go
语言的 slice
也是如此,因此个人心底里更愿意称其为动态数组!
切片 slice
的设计思路非常简单,内部包括三个重要变量,包括数组指针 ptr
,可访问元素长度 len
以及已分配容量 cap
.
When continually adding new elements into slices, has always reached the maximum capacity allocated, then it will automatically sliced expansion, otherwise it will volume reduction, enabling the ability to dynamically control!
- Number of array elements are specified, unspecified number of slices is
func TestArrayAndSlice(t *testing.T) {
// array
var arr1 [3]int
// slice
var arr2 []int
// [0 0 0] []
t.Log(arr1,arr2)
}
- Based slice array creation is a view of the original array
func TestArrayAndSliceByUpdate(t *testing.T) {
arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
// arr = [0 1 2 3 4 5 6 7 8 9]
t.Log("arr = ", arr)
s := arr[2:6]
// before update s = [2 3 4 5], arr = [0 1 2 3 4 5 6 7 8 9]
t.Logf("before update s = %v, arr = %v", s, arr)
s[0] = 666
// after update s = [666 3 4 5], arr = [0 1 666 3 4 5 6 7 8 9]
t.Logf("after update s = %v, arr = %v", s, arr)
}
- Add or delete elements return the new slice sliced
func TestArrayAndSliceIncreasing(t *testing.T) {
var s []int
fmt.Println("add new item to slice")
for i := 0; i < 10; i++ {
s = append(s, i)
fmt.Printf("s = %v, len(s) = %d, cap(s) = %d\n", s, len(s), cap(s))
}
fmt.Println("remove item from slice")
for i := 0; i < 10; i++ {
s = s[1:]
fmt.Printf("s = %v, len(s) = %d, cap(s) = %d\n", s, len(s), cap(s))
}
}
[index]
Access slice and slice the only elementslen
related to[start:end]
creating a new and original slice sliced justcap
about
func TestArrayAndSliceBound(t *testing.T) {
arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
s1 := arr[5:8]
// s1[0] = 5, s1[2] = 7
t.Logf("s1[0] = %d, s1[%d] = %d", s1[0], len(s1)-1, s1[len(s1)-1])
// s1 = [5 6 7], len(s1) = 3, cap(s1) = 5
t.Logf("s1 = %v, len(s1) = %d, cap(s1) = %d", s1, len(s1), cap(s1))
s2 := s1[3:5]
// s2[0] = 8, s2[1] = 9
t.Logf("s2[0] = %d, s2[%d] = %d", s2[0], len(s2)-1, s2[len(s2)-1])
// s2 = [8 9], len(s2) = 2, cap(s2) = 2
t.Logf("s2 = %v, len(s2) = %d, cap(s2) = %d", s2, len(s2), cap(s2))
}
- Only
map
noset
func TestMapAndSet(t *testing.T) {
m := map[string]string{
"name": "snowdreams1006",
"site": "https://snowdreams1006.github.io",
"lang": "go",
}
// https://snowdreams1006.github.io
if site, ok := m["site"]; ok {
t.Log(site)
} else {
t.Log("site does not exist ")
}
s := map[string]bool{
"name": true,
"site": true,
"lang": true,
}
// Pay attention to snowdreams1006
if _, ok := m["isFollower"]; ok {
t.Log("Have an eye on snowdreams1006")
} else {
s["isFollower"] = true
t.Log("Pay attention to snowdreams1006")
}
}
delete
Function deletes the setmap
key-value pairs
func TestMapAndSetByDelete(t *testing.T) {
m := map[string]string{
"name": "snowdreams1006",
"site": "https://snowdreams1006.github.io",
"lang": "go",
}
delete(m, "lang")
// delete lang successfully
if _,ok := m["lang"];!ok{
t.Log("delete lang successfully")
}
}
About Go
languages have built-in container is not Get
it? If you have a place to express wrong, please correct me ha, welcome to take a public number [Snow Dream Inn technologies] learning exchanges, a little progress every day!