Golang语言社区--Go语言基础第四节类型

大家好,我是Golang语言社区主编彬哥,这节给大家讲解Go语言中的类型。

Go语言中使用的类型包括:

基础类型

布尔类型(bool)

var b1 bool = true

整型

var v1 int = 12

浮点类型(float32、float64)

var f1 float32 = 12.0

复数类型(complex64、complex128)

var c1 complex64 = 3.2 + 12i

字符串(string)

var s string = “sina”

字符类型(rune)

代表单个的unicode字符

错误类型(error)

复合类型

指针(pointer)

数组(array)

[32] byte

切片(slice)

字典(map)

var word_count map[string] int

通道(chan)

用于协程间通信

结构体(struct)

接口(interface)

1、布尔类型

布尔类型不能接受其它类型的赋值,不支持自动或强制的类型转换,以下的示例是一些错误的用法:

var golang bool
golang = 1          // 错误
golang = bool(1)    // 错误

以下的用法是正确的:

var golang bool
golang = (1!=0)

2、整型

类型

长度

值范围

int8

1

-128 ~ 127

uint8(即byte)

1

0 ~ 255

int16

2

-32768 ~ 32767

uint16

2

0 ~ 65535

int32

4

-2147483648 ~ 2147483647

uint32

4

0 ~ 4294967295

int64

8

(-2^63) ~ (2^63-1)

uint64

8

0 ~ (2^64-1)

int

平台相关

平台相关

uint

平台相关

平台相关

uintptr

同指针

32位平台下为4字节,64位平台下为8字节

需要注意的是,int和int32是不同的类型, 不能相互赋值,例如:

var val2 int32
val1 := 64     // val1会被自动推导为int类型
var2 = val1    // error
var2 = int32(val1)  // ok

此外,不同类型的整型数不能直接比较,比如int8类型的数和int类型的数不能直接比较,但各种类型的整型变量都可以直接与字面常量(literal)进行比较,比如:

var i int32
var j int64

i,j = 1,2 

if i==j {         // error
    fmt.Println("i and j are equal.") 
}

if i==1 || j==2 {     // ok
    fmt.Println("i and j are equal.") 
}   

3、浮点型

Go语言中的float32和float64分别等价于C语言的float、double类型;

var i float32 = 12.1 
j := 64.0      // 自动推导为float64类型
j = i        // error
j = float64(i)  // ok  

判断两个浮点数是否相等,是根据不同精度来的:

import "math"

func IsEqual(f1, f2, p float64) bool {
    return math.Fdim(f1, f2) < p
}

其中,p是用户自定义的比较精度,比如p=0.00001。

4、字符类型

在Go语言中支持两个字符类型,一个是byte(实际上是uint8的别名),代表UTF-8字符串的单个字节的值;另一个是rune,代表单个Unicode字符。

关于rune相关的操作,可查阅Go标准库的unicode包;另外unicode/utf8包也提供了UTF8和Unicode之间的转换。

5、字符串

字符串支持下标读取操作:

str := "Hello world"
ch := str[0]
fmt.Printf("The length of \"%s\" is %d\n", str, len(str))
fmt.Printf("The 1st character of \"%s\" is '%c'\n", str, ch)

但字符串的内容在初始化后不能被修改,例如:

str := "Hello world"
str[0] = 'X'    // error

常用的字符串操作:

操作

含义

s1 + s2

字符串连接

len(s)

字符串长度

s[i]

取字符

字符串遍历有两种方式:

str := "Hello,世界"

// 以字节数组的方式遍历

for i := 0; i<len(str); i++ {
  ch := str[i]
  fmt.Println(i, ch)
}

 

// 以unicode字符方式遍历,每个字符的类型是rune

for i, ch := range str {
  fmt.Println(i, ch) 
}

 

6、数组

数组的声明方法比较多,比如:

[32] byte                // 字节数组
[2*N] struct {x, y int 32}     // 结构体数组
[1000] *float64           // 指针数组
[3][5] int             // 二维数组
[2][2][2] float64   

在声明数组时长度可以为一个常量或一个常量表达式,数组长度在定义以后就不可以再改变。

数组支持按下标读写元素,也支持range关键字的遍历,例如:

var array = [5] int {10,20,30,40,50}

for i, v := range array {
    array[i] = v*2;
}

for i, v := range array {
    fmt.Println(i, v) 
}

另外,数组是值类型,如果将数组作为函数参数传递,则在函数调用的时候该参数将发生数据复制,因此,在函数体中无法修改传入的数组的内容。

7、slice

数组切片的数据结构可以抽象为以下3个变量:

  • 一个指向原生数组的指针;
  • 数组切片中的元素个数;
  • 数组切片已分配的存储空间;

数组切片类似于C++中STL的std::vector<>,支持动态扩展数组,并且可以被作为函数参数传递而不会导致元素被复制。

创建数组切片有下面多种方式:

1、基于数组创建的方式

var myArray [10] int = [10] int {1,2,3,4,5,6,7,8,9,10}

var s1 = myArray[:]    // 基于myArray的所有元素创建数组切片
var s2 = myArray[:5]   // 基于myArray的前5个元素创建数组切片
var s3 = myArray[5:]   // 基于myArray从第5个元素开始的所有元素创建数组切片

2、直接创建数组切片的方式

s1 := make([] int,5)    // 创建一个初始元素个数为5的数组切片,元素初始值为0
s2 := make([] int,5, 10) // 创建一个初始元素个数为5的数组切片,元素初始值为0,并预留10个元素的存储空间
s3 := []int{1,2,3,4,5}  // 创建并初始化包含5个指定元素的数组切片

3、基于数组切片创建的方式

oldSlice := []int{1,2,3,4,5}
newSlice := oldSlice[:3]

操作数组元素的所有方法都适用于数组切片,比如数组切片也可以按下标读写元素,用len()获取元素个数,并支持使用range关键字来快速遍历所有元素。

数组切片支持可动态增减元素,内置的cap()和len()函数,分别返回数组切片分配的空间大小、当前存储的元素个数。

s := make([] int,5, 10)
fmt.Println("len(s)=",len(s))   // 5
fmt.Println("cap(s)=",cap(s))   // 10

使用append函数可以在数组切片尾端添加新元素:

s = append(s, 1,2,3)

如果追加的内容长度超过当前已分配的存储空间(即cap()返回值),数组切片会自动分配一块足够大的内存。

还可以将另一个数组切片追加到一个数组切片末端:

s2 := []int{8,9,10}
s = append(s, s2...)  // s2后面的省略号必须要有

数组切片的复制,如果两个slice不一样大,就会按其中较小的slice的元素个数进行复制,例如:

s1 := []int {1,2,3,4,5}
s2 := []int {5,4,7}
copy(s1, s2)  //只复制s2的3个元素到s1的前3个位置
copy(s2, s1)  //只复制s1的前3个元素到s2中

8、map

map是key-value结构的一个字典,类似于C++中STL的std::map<>。

例子:

type PersonInfo struct {
    ID string
    Name string
    Address string
}


func main() {
    var personDB map[string] PersonInfo      // 变量声明
    personDB = make(map[string] PersonInfo)    // 变量创建

    personDB["1"] = PersonInfo{"12345","Tom","Room 203"}  // 增加了一个键

    person, ok := personDB["1"]                // 查找
    if ok {
        fmt.Println("found person", person.Name, "with ID 1")
    } else {
        fmt.Println("Did not find person with ID 1")
    }

  delete(personDB, "1")        // 删除一个键
}

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏蘑菇先生的技术笔记

探索c#之函数创建和闭包

2647
来自专栏鸿的学习笔记

python的字典和集合

dict类型可以说是python里模块的命名空间,实例的属性,函数的关键字参数都有其的参与。

773
来自专栏Clive的技术分享

PHP常用array函数

函数名 函数作用 array_chunk 数组分割 array_column 获取数组的某一列 array_combine 两个数组分别...

2986
来自专栏debugeeker的专栏

《coredump问题原理探究》Linux x86版4.3节函数的逆向之条件结构

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xuzhina/article/detai...

742
来自专栏编程

Shell 数组

Shell中数据类型不多,比如说字符串,数字类型,数组。数组是其中比较重要的一种,同时Shell中的数组不像JAVA/C,只能是一维数组,没有二维数组;数组元素...

1820
来自专栏web前端

JavaScript基础学习--14 json、数组

Demos:   https://github.com/jiangheyan/JavaScriptBase 一、json      1、格式与取值:{key:...

19310
来自专栏青枫的专栏

java基础学习_基础语法(下)02_day06总结

============================================================================= ==...

451
来自专栏向治洪

Koltin数据类之解构申明

所谓的解构声明就是将一个对象解构(destructure)为多个变量,也就是意味着一个解构声明会一次性创建多个变量.简单的来说,一个解构声明有两个动作: 声明了...

20610
来自专栏老司机的技术博客

宝宝都能学会的python编程教程15:高级特性2

生成器 如果你想要一百万个数,而这些数里只有一百个数是你经常要用的,剩下的都几乎不怎么会用到,那么如果直接把这一百万个数全部放在list中是不明智的因为这会浪费...

2493
来自专栏DHUtoBUAA

查找数组中重复的数字

        题目来源于《剑指Offer》中的面试题3:找出数组中重复的数字。   // 题目:在一个长度为n的数组里的所有数字都在0到n-1的范围内。数组中...

3646

扫码关注云+社区