golang之数据结构

 

 

 

4种:bool/int/uint/uintptr(其中bool类型的零值为false,其余类型的零值为0)

4种:float32/float64/complex64/complex126 (零值为0)

8种:int8/int16/int32/int64/uint8/uint16u/int32/uint64 (零值为0)其中byte=int8,rune=int32,-----无符号数往往只有在位运算或其它特殊的运算场景才会使用,一般不用。

string:(零值为空字符串)

 复杂类型:

指针

数组

切片

哈希

结构体

函数

接口

channel

 --------------------------------------------------------------------

1、整型。 

          (1) byte与rune类型有一个共性,即:它们都属于别名类型byte是uint8的别名类型,而rune则是int32的别名类型。byte类型的值需用8个比特位表示,其表示法与uint8类型无异。因此我们就不再这里赘述了。我们下面重点说说rune类型。  

         (2)一个rune类型的值即可表示一个Unicode字符。Unicode是一个可以表示世界范围内的绝大部分字符的编码规范。用于代表Unicode字符的编码值也被称为Unicode代码点。一个Unicode代码点通常由“U+”和一个以十六进制表示法表示的整数表示。例如,英文字母“A”的Unicode代码点为“U+0041”。rune类型的值需要由单引号“'”包裹。例如,'A'或'郝'。这种表示方法一目了然。不过,我们还可以用另外几种形式表示rune类型值。请看下表。   

          (3)另外,在rune类型值的表示中支持几种特殊的字符序列,即:转义符。它们由“\”和一个单个英文字符组成。如下表所示。

 

     (4)整数的表示:十进制、八进制(以0开头)、十六进制(以0x开头)。在数学中整数一般是以10进制来表示的,而在计算机中整数则必是以2进制来表示和存储的。当然,在计算机科学领域,整数的表示形式还包括了8进制和16进制。

2浮点型

     (1)浮点数类型有两个,即float32和float64。你可能已经想到,存储这两个类型的值的空间分别需要4个字节和8个字节。优先使用float64类型。
     (2)浮点数类型有两种表示。一般由整数部分、小数点“.”和小数部分组成。其中,整数部分和小数部分均由10进制表示法表示。不过还有另一种表示方法。那就是在其中加入指数部分。指数部分由“E”或“e”以及一个带正负号的10进制数组成。比如,3.7E-2表示浮点数0.037。又比如,3.7E+1表示浮点数37。有时候,浮点数类型值的表示也可以被简化。比如,37.0可以被简化为37。又比如,0.037可以被简化为.037。
    (3)浮点数的相关部分只能由10进制表示法表示,而不能由8进制表示法或16进制表示法表示。比如,03.7表示的一定是浮点数3.7。

3、复数

           Go语言提供了两种精度的复数类型:complex64和complex128,分别对应float32和float64两种浮点数精度。内置的complex函数用于构建复数,内建的real和imag函数分别返回复数的实部和虚部:

var x complex128 = complex(1, 2) // 1+2i
var y complex128 = complex(3, 4) // 3+4i
fmt.Println(x*y)                 // "(-5+10i)"
fmt.Println(real(x*y))           // "-5"
fmt.Println(imag(x*y))           // "10"

4、布尔类型

        一个布尔类型的值只有两种:true和false。且bool类型的变量只能接受true、false和结果为布尔类型的表达式。

        if和for语句的条件部分都是布尔类型的值,并且==和<等比较操作也会产生布尔型的值。一元操作符!对应逻辑非操作,因此!true的值为false,更罗嗦的说法是(!true==false)==true,虽然表达方式不一样,不过我们一般会采用简洁的布尔表达式,就像用x来表示x==true

布尔值可以和&&(AND)和||(OR)操作符结合,并且有短路行为:如果运算符左边值已经可以确定整个布尔表达式的值,那么运算符右边的值将不再被求值,因此下面的表达式总是安全的:

s != "" && s[0] == 'x'

其中s[0]操作如果应用于空字符串将会导致panic异常。

因为&&的优先级比||高(助记:&&对应逻辑乘法,||对应逻辑加法,乘法比加法优先级要高),下面形式的布尔表达式是不需要加小括弧的:

if 'a' <= c && c <= 'z' ||
    'A' <= c && c <= 'Z' ||
    '0' <= c && c <= '9' {
    // ...ASCII letter or digit...
}

布尔值并不会隐式转换为数字值0或1,反之亦然。必须使用一个显式的if语句辅助转换:

i := 0
if b {
    i = 1
}

如果需要经常做类似的转换, 包装成一个函数会更方便:

// btoi returns 1 if b is true and 0 if false.
func btoi(b bool) int {
    if b {
        return 1
    }
    return 0
}

数字到布尔型的逆转换则非常简单, 不过为了保持对称, 我们也可以包装一个函数:

// itob reports whether i is non-zero.
func itob(i int) bool { return i != 0 }

---------------------------------------------------------------------------------
---------------------------------------------------------------------------------
1、数组
2、结构体
3、切片
4、哈希表
(1)键值对=key/value,
(2)无序
(3)所有的key都有相同的数据类型,且必须是支持==比较运算符,所有的key都是互不相同的,浮点数类型支持相等运算符比较的,但是将浮点数用做key类型则是一个坏的想法。
(4)所有的value也有着相同的类型,对于V对应的value数据类型则没有任何的限制,但是key和value之间可以是不同的数据类型。
(5)创建map:
ages := make(map[string]int)
map["wangjialun"] = 45
map["igoodful"] = 99
map["zhangdi"] = 100
delete(ages, "igoodful")
---------------
ages := map[string]int{}
map["wangjialun"] = 45
map["igoodful"] = 99
map["zhangdi"] = 100
delete(ages, "igoodful")
---------------
ages := map[string]int{"wangjialun":45, "igoodful":99, "zhangdi":100}
delete(ages, "igoodful")
(6)遍历map

要想遍历map中全部的key/value对的话,可以使用range风格的for循环实现,和之前的slice遍历语法类似。下面的迭代语句将在每次迭代时设置name和age变量,它们对应下一个键/值对:

for name, age := range ages {
    fmt.Printf("%s\t%d\n", name, age)
}
(7)排序遍历

Map的迭代顺序是不确定的,并且不同的哈希函数实现可能导致不同的遍历顺序。在实践中,遍历的顺序是随机的,每一次遍历的顺序都不相同。这是故意的,每次都使用随机的遍历顺序可以强制要求程序不会依赖具体的哈希函数实现。如果要按顺序遍历key/value对,我们必须显式地对key进行排序,可以使用sort包的Strings函数对字符串slice进行排序。下面是常见的处理方式:

import "sort"

var names []string
for name := range ages {
    names = append(names, name)
}
sort.Strings(names)
for _, name := range names {
    fmt.Printf("%s\t%d\n", name, ages[name])
}
 
 

内置的make函数可以创建一个map:

ages := make(map[string]int) // mapping from strings to ints

我们也可以用map字面值的语法创建map,同时还可以指定一些最初的key/value:

ages := map[string]int{
    "alice":   31,
    "charlie": 34,
}

这相当于

ages := make(map[string]int)
ages["alice"] = 31
ages["charlie"] = 34

因此,另一种创建空的map的表达式是map[string]int{}

Map中的元素通过key对应的下标语法访问:

ages["alice"] = 32
fmt.Println(ages["alice"]) // "32"

使用内置的delete函数可以删除元素:

delete(ages, "alice") // remove element ages["alice"]

所有这些操作是安全的,即使这些元素不在map中也没有关系;如果一个查找失败将返回value类型对应的零值,例如,即使map中不存在“bob”下面的代码也可以正常工作,因为ages["bob"]失败时将返回0。

ages["bob"] = ages["bob"] + 1 // happy birthday!

而且x += yx++等简短赋值语法也可以用在map上,所以上面的代码可以改写成

ages["bob"] += 1

更简单的写法

ages["bob"]++

但是map中的元素并不是一个变量,因此我们不能对map的元素进行取址操作:

_ = &ages["bob"] // compile error: cannot take address of map element

禁止对map元素取址的原因是map可能随着元素数量的增长而重新分配更大的内存空间,从而可能导致之前的地址无效。






 

posted @ 2019-07-24 17:09  igoodful  阅读(1648)  评论(0编辑  收藏  举报