Go language Learning (iv) Common types introduction

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed.

1. Boolean type

var v1 boolv1 = true;v2 := (1==2) // v2也会被推导为bool类型

2. Integral type

类 型  长度(字节)     值 范 围int8    1              128 ~ 127uint8(即byte)1       0 ~ 255int16   2              32 768 ~ 32 767uint16  2               0 ~ 65 535int32   4              2 147 483 648 ~ 2 147 483 647uint32  4               0 ~ 4 294 967 295int64   8      9 223 372 036 854 775 808 ~ 9 223 372 036 854 775 807uint64  8       0 ~ 18 446 744 073 709 551 615int     平台相关        平台相关uint    平台相关        平台相关uintptr 同指针         在32位平台下为4字节,64位平台下为8字节var value2 int32value1 := 64 // value1将会被自动推导为int类型value2 =value1  //编译失败:cannot use value1 (type int) as type int32 in assignment。//使用强制类型转换可解决value2 = int32(value1)

3. Numerical operations

常规运算:+、-、*、/和%比较运算: > 、 < 、 == 、 >= 、 <= 和 !=需要注意:两个不同类型的整型数不能直接比较,比如 int8 类型的数和 int类型的数不能直接比较,但各种类型的整型变量都可以直接与字面常量(literal)进行比较,比如:
varint32varint64i, j = 1, 2if// 编译错误fmt.Println("i and j are equal.")}if i == 1 || j == 2// 编译通过fmt.Println("i and j are equal.")}

4. Bit arithmetic

x << y  左移 x >> y  右移 x ^ y   异或  x & y   与  x | y   或 ^x      取反  

5. Floating-point types

Go语言定义了两个类型 float32 和 float64 ,其中 float32 等价于C语言的 float 类型,float64 等价于C语言的 double 类型。var fvalue1 float32fvalue1 = 12fvalue2 := 12.0 // 如果不加小数点,fvalue2会被推导为整型而不是浮点型对于以上例子中类型被自动推导的 fvalue2 ,需要注意的是其类型将被自动设为 float64 ,而不管赋给它的数字是否是用32位长度表示的。因此,对于以上的例子,下面的赋值将导致编译错误:fvalue1 = fvalue2而必须使用这样的强制类型转换:fvalue1 = float32(fvalue2)

5.1 Floating-point comparison

因为浮点数不是一种精确的表达方式,所以像整型那样直接用 == 来判断两个浮点数是否相等是不可行的,这可能会导致不稳定的结果。下面是一种推荐的替代方案:
import"math"// p为用户自定义的比较精度,比如0.00001funcfloat64bool {    return math.Fdim(f1, f2) < p}

6. plural

复数实际上由两个实数(在计算机中用浮点数表示)构成,一个表示实部(real),一个表示虚部(imag)。如果了解了数学上的复数是怎么回事,那么Go语言的复数就非常容易理解了。

6.1 Plural representation

var value1 complex64 // 由2个float32构成的复数类型value1 = 3.2 + 12ivalue2 := 3.2 + 12i // value2是complex128类型value3 := complex(3.2, 12) // value3结果同 value2

6.2 Real part and imaginary part

对于一个复数 z = complex(x, y) ,就可以通过Go语言内置函数 real(z) 获得该复数的实部,也就是 x ,通过 imag(z) 获得该复数的虚部,也就是 y 。

7. String

Go语言中字符串的声明和初始化非常简单,举例如下:
varstring  // 声明一个字符串变量"Hello world"// 字符串赋值ch := str[0// 取字符串的第一个字符fmt.Printf("The length of \"%s\" is %d \n"len(str))fmt.Printf("The first character of \"%s\" is %c.\n", str, ch)
输出结果为:The length of "Hello world" is 11The first character of "Hello world" is H.
字符串的内容可以用类似于数组下标的方式获取,但与数组不同,字符串的内容不能在初始化后被修改,比如以下的例子:str := "Hello world" // 字符串也支持声明时进行初始化的做法str[0] = 'X'  // 编译错误编译器会报类似如下的错误:cannot assign to str[0]如果想修改字符串的内容,可以通过如下的方式修改:
"hello"c := []rune//将字符串s转成rune数组c[0'x'//修改rune数组中的第一个元素为xstring//根据rune数组创建一个新的字符串fmt.Println("s2=",s2)
运行结果:    s2= xello

7.1 String Manipulation

x + y   字符串连接  "Hello" + "123" // 结果为Hello123len(s)  字符串长度  len("Hello") // 结果为5s[i]    取字符  "Hello" [1] // 结果为'e'

7.2 Multi-line string

使用多行字符串需要小心,例如:s := "Hello "    +"world"编译时会被自动转换成:s := "Hello ";    +"world";此时会编译失败,报错:invalid operation: + untyped string  正确的多行写法是这样的:s := "Hello " +    "world"Go 就不会在错误的地方插入分号。另一种写法是使用反引号 ` 作为原始字符串符号:s := `Hello      world`

7.3 String Traversal

Go语言支持两种方式遍历字符串。一种是以字节数组的方式遍历:
"abc中国"len(str)for i := 0; i < n; i++ {    // 依据下标取字符串中的字符,类型为byte    fmt.Printf("i=%v\n", ch)}
输出结果:i=97    //ai=98    //bi=99    //ci=228   //中字的第一字节,每个中文字符在UTF-8中占3个字节i=184   //中字的第二个字节i=173   //中字的第三个字节i=229   //国字的第一个字节i=155   //国字的第二个字节i=189   //国字的第三个字节
另一种是以Unicode字符遍历,以Unicode字符方式遍历时,每个字符的类型是 rune (早期的Go语言用 int 类型表示Unicode字符),而不是byte.
"abc中国"forrange str{  //range关键字在数组中有介绍    fmt.Println(i,ch)  //ch的类型为rune}
//输出结果:0 971 982 993 20013   6 22269

8. Character types

在Go语言中支持两个字符类型,一个是 byte (实际上是 uint8 的别名),代表UTF-8字符串的单个字节的值;另一个是 rune ,代表单个Unicode字符。出于简化语言的考虑,Go语言的多数API都假设字符串为UTF-8编码。尽管Unicode字符在标准库中有支持,但实际上较少使用。

9. Arrays

以下为一些常规的数组声明方法:[32]byte // 长度为32的数组,每个元素为一个字节[2*N] struct { x, y int32 } // 复杂类型数组[1000]*float64  // 指针数组[3][5]int  // 二维数组[2][2][2]float64  // 等同于[2]([2]([2]float64))在Go语言中,数组长度在定义后就不可更改,在声明时长度可以为一个常量或者一个常量表达式(常量表达式是指在编译期即可计算结果的表达式)。

9.1 Elements of Access

可以使用数组下标来访问数组中的元素。与C语言相同,数组下标从0到len(array)-1,下面的示例遍历整型数组并逐个打印元素内容:
//通过for循环遍历for i := 0len(array); i++ {    fmt.Println("Element""of array is", array[i])}//Go语言还提供了一个关键字range,用于便捷地遍历容器中的元素。//当然,数组也是range的支持范围。上面的遍历过程可以简化为如下的写法:forrange array {  //k相当于索引,v相当于值    fmt.Println("Array element[""]=", v)  }

9.2 Value Operation

需要特别注意的是,在Go语言中数组是一个值类型(value type)。所有的值类型变量在赋值和作为参数传递时都将产生一次复制动作。如果将数组作为函数的参数类型,则在函数调用时该参数将发生数据复制。因此,在函数体中无法修改传入的数组的内容,因为函数内操作的只是所传入数组的一个副本。下面用例子来说明这一特点:
func main(){    [5]int{1,2,3,4,5}    modify(array)    fmt.Println("In main(),array values:",array)}func[5int){    array[0] = 10    fmt.Println("In modify(),array values:",array)}
//输出结果:In modify(), array values: [10 2 3 4 5]In main(), array values: [1 2 3 4 5]
从执行结果可以看出,函数 modify() 内操作的那个数组跟 main() 中传入的数组是两个不同的实例。那么,如何才能在函数内操作外部的数据结构呢?这个就要用到后接下来要讲的数组切片.

10. Array slicing

在前一节里我们已经提过数组的特点:数组的长度在定义之后无法再次修改;数组是值类型,每次传递都将产生一份副本。显然这种数据结构无法完全满足开发者的真实需求。Go语言提供了数组切片(slice)这个非常酷的功能来弥补数组的不足,可以随时动态扩充存放空间,并且可以被随意传递而不会导致所管理的元素被重复复制。有点类似于java中的集合.数组切片的数据结构可以抽象为以下3个变量:一个指向原生数组的指针;数组切片中的元素个数;数组切片已分配的存储空间。

10.1 Creating an Array slice

(1)基于已存在数组创建,数组切片可以只使用数组的一部分元素或者整个数组来创建,甚至可以创建一个比所基于的数组还要大的数组切片。
varMyArray[Ten]int=[Ten]int{1, 2, 3, 4, 5, 6, 7, 8, 9, ten}//Create an array slice based on the first 5 elements of the arrayvarMyslice []int= myarray[: 5]fmt. Println ("Elements of MyArray:") for_, V: =Rangemyarray{FMT. Print (V," ")}fmt. Println ("\nelements of Myslice:") for_, v:=Rangemyslice{FMT. Print (V," ")}
//输出结果:Elements of myArray:1 2 3 4 5 6 7 8 9 10Elements of mySlice:1 2 3 4 5
Go语言支持用 myArray[first:last] 这样的方式来基于数组生成一个数组切片,而且这个用法还很灵活,比如下面几种都是合法的。a.基于 myArray 的所有元素创建数组切片:mySlice = myArray[:]b.基于 myArray 的前5个元素创建数组切片:mySlice = myArray[:5]c.基于从第5个元素开始的所有元素创建数组切片:mySlice = myArray[5:](2)通过make()函数直接创建数组切片创建一个初始元素个数为5的数组切片,元素初始值为0:mySlice1 := make([]int,5)创建一个初始元素个数为5的数组切片,元素初始值为0,并预留10个元素的存储空间:mySlice2 := make([]int,5,10) 通过cap()函数可以获取切片的分配空间,len()函数可以知道当前已存储的元素个数.
fmt.Println("len(mySlice2):"len(mySlice2))fmt.Println("cap(mySlice2):"cap(mySlice2))
//输出结果:len(mySlice2): 5cap(mySlice2): 10
当然,事实上还会有一个匿名数组被创建出来,只是不需要我们来操心而已。(3)直接在声明的时候并初始化mySlice3 := []int{8,9,10}(4)基于数组切片创建数组切片oldSlice := []int{1,2,3,4,5}newSlice := oldSlice[:3] //基于oldSlice的前3个元素创建

10.2 element traversal of array slices

操作数组的所有方法都适合数组切片,通过上面的代码也可以看得出来共有2种方式:for循环遍历,或者for循环结合range来操作

10.3 Dynamic increment and decrement of array slice elements

与数组相比,数组切片多了一个存储能力的概念,即元素个数和分配的空间可以是两个不同的值,合理地设置存储能力的值,可以大幅降低数组切片内部重新分配内存和搬送内存块的频率,从而大大提高程序性能。通过append()函数可以在切片后面追加元素,例如:mySlice = append(mySlice, 8, 9, 10) append()函数的第二个参数是个不定的参数,有点类似java中的可变参数,甚至可以追加1个数组切片mySlice2 := []int{8,9,10}mySlice = append(mySlice,mySlice2...) //注意:这3个...点不能省略,否则编译失败

10.4 Content Replication

通过copy()函数,可以将一个数组切片复制到另一个数组切片中,如果2个的数组切片不一样大,则会按其中较小的那个数组切片的元素个数进行复制.slice1 := []int{1,2,3,4,5}slice2 := []int{5,4,3}copy(slice2,slice1) //只会复制slice1的前3个元素到slice2中,slice2中的值被自动替换copy(slice1,slice2) //只会复制slice2的3个元素到slice1的前3个位置,该3个位置的值自动替换,其他的不变

11.map

在C++/Java中,map一般都以库(导包)的方式提供,在C++/Java中, 而在Go中,使用map 不需要引入任何库,并且用起来也更加方便。看下面的例子:
typePersonInfostruct{IDstringNamestringAddressstring}funcMain () {varPersondbMap[string] PersonInfo//Declaration of a Key=string,value=personinfo mapPERSONDB = Make(Map[string] PersonInfo)//Initialize with make    //Insert a few data into this mappersondb["0"] = personinfo{"12345","Tom","203,..."} persondb["1"] = personinfo{"1","Jack","101,..."}//....    //Find the information for key 12345 from this mapperson, OK: = persondb["0"]//If found, then ok=true, otherwise =false    ifok{FMT. Println ("Found person", person. Name,"with ID", Person.id)}Else{FMT. Println ("did not find the person")    }}
//运行结果:Found person Tom with ID 12345

Statement of the 11.1map

Creation of 11.2map

(1)通过make()函数创建
var  myMap map  [int ] string  MyMap = make  (map  [ int ] string ) //can also be written as a statement: MyMap: = Make (map[int]string)  mymap[0 ] =  "1"  //assignment  MyMap [1 ] =  "2"  result,_: = MyMap [0 ] //this uses the anonymous variable  fmt. Println ( "mymap[0]=" , result) fmt. Println ( "mymap[1]=" , Mymap[1 ])  
//运行结果:myMap[0]= 1myMap[1]= 2
通过make创建的时候,还可以指定其初始容量myMap2 := make(map[int]string,100)(2)方式2,通过{}赋值的方式创建
map[int]string{    0:"张三",    1:"李四",}fmt.Println("myMap3[0]=",myMap3[0])fmt.Println("myMap3[1]=",myMap3[1])
//运行结果:myMap3[0]= 张三myMap3[1]= 李四

11.3 Deletion of elements

通过delete()函数完成,形如:delete(map变量名,map的key)如果要删除的元素没有对应的key,则什么都不发生,但是如果传入的map变量的值是 nil ,该调用将导致程序抛出异常(panic)。

11.4 Searching for elements

map通过key查找,可以返回2个变量,第一个为对应key的值,第二个为是否查找成功的bool,形如:
map[key]if ok{    //找到了,处理value}else{    //未找到}
当然,如果你很确定该key一定能够找到对应的值的话,那就可以直接使用一个变量来接收,例如:value := map[key]或者,第二个参数用匿名参数来接收,例如:value,_ := map[key]

11.5 Traversal of elements

(1)使用for循环遍历    
make(map[int]int)myMap[0] = 100myMap[1] = 101myMap[2] = 102for i:=0;i<len(myMap);i++ {    fmt.Println("key=",i," value=",myMap[i])}
运行结果:key= 0  value= 100key= 1  value= 101key= 2  value= 102
(2)使用for循环结合range关键字遍历
map[int]int{    0 : 10,    1 : 20,    2 : 30,}forrange myMap{    fmt.Println("key=",k," value=",v)}
运行结果:key= 0  value= 10key= 1  value= 20key= 2  value= 30

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.