《go语言编程》学习笔记二

变量

变量声明
var v1 int
var v2 string
var v3 [10]int // 数组
var v4 []int // 数组切片
var v5 struct {
f int
}
var v6 *int // 指针
var v7 map[string]int // map, key为string类型, value为int类型
var v8 func(a int) int

在go语言中,并不需分号作为结束符,并且在go语言中,引入了var关键字,类型名称放在变量名称之后
为了避免大量的重复var。还可以写成下面的方式声明变量,

var (
v1 int
v2 string
)
变量初始化
var v1 int = 10 // 正确的使用方式1
var v2 = 10 // 正确的使用方式2,编译器可以自动推导出v2的类型
v3 := 10 // 正确的使用方式3,编译器可以自动推导出v3的类型

上面三种方式都是go语言声明变量的正确方式,可以看见,第三种方式大大减少了字符量,其中:=表示的是同时进行声明和初始化工作。需要注意的是,:=左边的的变量不能是已经被声明过的,如下:

var i int
i := 2

这样会编译错误

变量赋值
var v10 int
v10 = 123

需要注意的是:在go语言中,变量声明和变量赋值是两个不同的概念,同时在go语言中,可以实现多重赋值功能,比如下面交换变量i和变量j的语句:

i, j = j, i

和其他编程语言相比,真是太好用了,

匿名变量
//假 设 GetName() 函 数 的 定 义 如 下 , 它 返 回 3 个 值 , 分 别 为firstName 、 lastName 和
nickName:
func GetName() (firstName, lastName, nickName string) {
return "May", "Chan", "Chibi Maruko"
}

如果想要只是获得nickName ,则只需要以下语句即可:

_, _, nickName := GetName()

go语言的这种写法,不会像其他语言那样,声明一大堆无用的变量
go语言的这种写法让代码十分德尔简洁,便于阅读,理解和维护。

常量

字面常量

字面常量通常是指程序中硬编码的常量,在其他语言中,常量都有特定的类型,比如int、long、float等等。但是在go语言中,常量是没有类型的,只要这个常量在相应类型的值域范围内,就可以作为该类型的常量,比如上面的常量-12,它可以赋值给int、 uint、 int32、int64、 float32、 float64、 complex64、 complex128等类型的变量。

常量的定义

在g语言中通过const关键字来定义常量,如下:

const Pi float64 = 3.14159265358979323846
const zero = 0.0 // 无类型浮点常量
const (
size int64 = 1024
eof = -1 // 无类型整型常量
)
const u, v float32 = 0, 3 // u = 0.0, v = 3.0,常量的多重赋值
const a, b, c = 3, 4, "foo"
// a = 3, b = 4, c = "foo", 无类型整型和字符串常量

同时,在go语言中,也是可以定义类型的, 但是不是必须定义。

预定义常量

Go语言预定义了这些常量: true、 false和iota

iota是什么:

iota是一个可被编译器修改的常量,在每一个const关键字出现时被重置为0,然后在下一个const出现之前,每出现一次iota,其所代表的数字会自动增1

const ( // iota被重设为0
c0 = iota // c0 == 0
c1 = iota // c1 == 1
c2 = iota // c2 == 2
)
const (
a = 1 << iota // a == 1 (iota在每个const开头被重设为0)
b = 1 << iota // b == 2
c = 1 << iota // c == 4
)
const (
u = iota * 42 // u == 0
v float64 = iota * 42 // v == 42.0
w = iota * 42 // w == 84
)
const x = iota // x == 0 (因为iota又被重设为0了)
const y = iota // y == 0 (同上)

如果两个const的赋值语句的表达式是一样的,那么可以省略后一个赋值表达式。

const ( // iota被重设为0
c0 = iota // c0 == 0
c1 // c1 == 1
c2 // c2 == 2
)
const (
a = 1 <<iota // a == 1 (iota在每个const开头被重设为0)
b // b == 2
c // c == 4
)
枚举

枚举指一系列相关的常量
在go语言中,并不存在其中语言中的枚举关键字enum
如下面是一个表示星期的枚举:

const (
Sunday = iota
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
numberOfDays // 这个常量没有导出
)

在这里需要注意的是:在go语言中,以大写字母开头的常量,在其他包中可见,以小写字母开头的常量,只能在本包中可见,在其他包中不可见。所以上面的numberOfDays不能够被其他包导出。

类型

go语言中的类型有下面几种:
布尔类型: bool。
整型: int8、 byte、 int16、 int、 uint、 uintptr等。
浮点类型: float32、 float64。
复数类型: complex64、 complex128。
字符串: string。
字符类型: rune。
错误类型: error。
同时go语言也支持下面的几种复合类型:
指针(pointer)
数组(array)
切片(slice)
字典(map)
通道(chan)
结构体(struct)
接口(interface)
同时go语言也有封装int、 uint和uintptr等类型,在常规的开发中,用到int等类型即可。

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

在go语言中,和其他语言一样,布尔类型不能接受其他类型的赋值,不支持自动或强制的类型转换

整型


需要注意的是int和int32是不同的类型,两个不同类型的整型数不能直接比较

位运算

浮点型:

Go语言定义了两个类型float32和float64,其中float32等价于C语言的float类型,float64等价于C语言的double类型。

var fvalue1 float32
fvalue1 = 12
fvalue2 := 12.0 // 如果不加小数点, fvalue2会被推导为整型而不是浮点型

因为浮点数不是一种精确的表达方式,所以像整型那样直接用==来判断两个浮点数是否相等是不可行的,这可能会导致不稳定的结果
下面是一种替换方案;

import "math"
// p为用户自定义的比较精度,比如0.00001
func IsEqual(f1, f2, p float64) bool {
return math.Fdim(f1, f2) < p
}

复数类型:

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

在go语言中,如果复数表示为:z = complex(x, y),那么:real(z)获得实部x,imag(z)获得虚部y。

字符串

var str string // 声明一个字符串变量
    str = "Hello world" // 字符串赋值
    ch := str[0] // 取字符串的第一个字符
    fmt.Printf("The length of \"%s\" is %d \n", str, len(str))
    fmt.Printf("The first character of \"%s\" is %c.\n", str, ch)

打印的结果为:

go语言中字符串的操作

go语言中遍历字符串
str := "Hello,世界"
    n := len(str)
    for i := 0; i < n; i++ {
        ch := str[i] // 依据下标取字符串中的字符,类型为byte
        fmt.Println(i, ch)
    }

打印结果:

字符类型:

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

数组:

[32]byte // 长度为32的数组,每个元素为一个字节
[2*N] struct { x, y int32 } // 复杂类型数组
[1000]*float64 // 指针数组
[3][5]int // 二维数组
[2][2][2]float64 // 等同于[2]([2]([2]float64))

go语言中国数组长度定义之后不可修改,使用arrLength := len(arr)表示获取获得arr数组元素个数。
遍历数组的方法:

for i := 0; i < len(array); i++ {
fmt.Println("Element", i, "of array is", array[i])
}

在go语言中还有一个range关键字。用于便捷的遍历数组

for i, v := range array {
fmt.Println("Array element[", i, "]=", v)
}

在go语言中,数组是一个值类型:

数组切片

一个指向原生数组的指针;
数组切片中的元素个数;
数组切片已分配的存储空间。
数组切片弥补了数组中的不足。
数组切片添加了一系列管理功能,可以随时动态扩充存放空间,并且可以被随意传递而不会导致所管理的元素被重复复制。

// 先定义一个数组
    var myArray [10]int = [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
    // 基于数组创建一个数组切片
    var mySlice []int = myArray[:5]
    fmt.Println("Elements of myArray: ")
    for _, v := range myArray {
        fmt.Print(v, " ")
    }
    fmt.Println("\nElements of mySlice: ")
    for _, v := range mySlice {
        fmt.Print(v, " ")
    }
    fmt.Println()

map

map是一堆键值对的未排序集合

// PersonInfo是一个包含个人详细信息的类型
type PersonInfo struct {
    ID string
    Name string
    Address string
}

func main() {
    var personDB map[string]PersonInfo
    personDB = make(map[string]PersonInfo)
    // 往这个map里插入几条数据
    personDB["12345"] = PersonInfo{"12345", "Tom", "Room 203,..."}
    personDB["1"] = PersonInfo{"1", "Jack", "Room 101,..."}
    // 从这个map查找键为"1234"的信息
    person, ok := personDB["1234"]
    // ok是一个返回的bool型,返回true表示找到了对应的数据
    if ok {
        fmt.Println("Found person", person.Name, "with ID 1234.")
    } else {
        fmt.Println("Did not find person with ID 1234.")
    }
}
声明变量
var myMap map[string] PersonInfo
创建

可以使用Go语言内置的函数make()来创建一个新map

myMap = make(map[string] PersonInfo)

也可以选择是否在创建时指定该map的初始存储能力,下面的例子创建了一个初始存储能力为100的map:

myMap = make(map[string] PersonInfo, 100)

创建并初始化:

myMap = map[string] PersonInfo{
"1234": PersonInfo{"1", "Jack", "Room 101,..."},
}
赋值
myMap["1234"] = PersonInfo{"1", "Jack", "Room 101,..."}
删除
delete(myMap, "1234")

delete()是go语言中的一个内置函数,用于删除容器中的内容。

元素查找:
value, ok := myMap["1234"]
if ok { // 找到了
// 处理找到的value
}

判断是否成功找到特定的键,不需要检查取到的值是否为nil,只需查看第二个返回值ok。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值