YMLiang

数据类型转换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
   通过类型前置加一个圆括号
T(表达式)
T表示要转化的类型,表达式包括:变量,数值,函数返回值等
int(8.2)
int(80.5)
布尔型无法与其他类型转换

int转换为string OK
string转换为int NO


eg:
chinese := 90
english := 90.9
result := string(chinese)

fmt.Println(chinese,english,result)

90 90.9 Z

常量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
常量是一个简单值的标识符,在程序运行时,不会被修改的量。

常量中的数据类型只可以是布尔型、数字型(整数型、浮点型和复数)和字符串型。

常量的定义格式:
const identifier [type] = value

你可以省略类型说明符 [type],因为编译器可以根据变量的值来推断其类型。
显式类型定义: const b string = "abc"
隐式类型定义: const b = "abc"

多个相同类型的声明可以简写为:
const c_name1, c_name2 = value1, value2

常量用于枚举(常量组):
也可以使用 const()定义块,定义多个,每个常量单独一行,例如
const (
c6 = 42
c7 = 1000
)

const()块定义时,如果常量未给出定义,则延续上面的定义规则,例如:
const (
c7 = 42
c8 // c8 = 42
c9 // c9 = 42
)

iota迭代定义常量:
const配合iota关键字使用,可以定义一组由0开始+1迭代的常量 演示语法:

const (
gender_secret = iota
gender_male // = iota
gender_female // = iota
)
此时,三个常量值,分别是,0, 1, 2 iota的规则是:若iota出现在const()中,那么const()定义的第一行的iota就是0,第二行就是0+1=1,不论iota是否被常量使用。演示如下:

const (
c1 = 42 // iota = 0,虽然未使用iota,但后边(const()中)有使用,此时iota被初始化为0,下面每行累加1
c2 = iota // iota = 1,iota继续累加,使用了iota
c3 = 1024 // iota = 2,同样未使用,但iota的值继续累加。c3 被定义为1024
c4 // iota = 3,c4延续上面的定义c4=1024,iota继续累加
c5 = iota // iota = 4,iota继续累加,使用了iota
c6 = iota // iota = 5,iota继续累加,使用了iota
)
此时结果为:42, 1, 1024, 1024, 4, 5

函数

func 和 JavaScript中定义类似 定义之后在main中来调用,流程很好理解

  • Go中函数为一等公民:

    1. 函数本身可以作为值来传递
    2. 支持匿名函数和闭包
    3. 函数可以满足接口
  • 如何声明函数(函数定义)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
     func 函数名 (参数列表) (返回值参数列表){
    //函数体
    }

    参数列表,参数就像一个占位符,当函数被调用时,你可以将值传递给参数,这个值被称为实际参数。参数列表指定的是参数类型、顺序、及参数个数。参数是可选的,也就是说函数也可以不包含参数
    返回类型,函数返回一列值。return_types 是该列值的数据类型。有些功能不需要返回值,这种情况下 return_types 不是必须的。

    这里以一个加法的栗子说明:

    func add (a int,b int) int {
    var sum int = a + b
    return sum
    }

    func main() {
    //函数调用
    cd := add(10,20)
    fmt.Println(cd)
    }

    输出:30

    下面再来写一个有多个返回值的
    func add(a int, b int) (int,string){
    var sum int = a + b
    str := strconv.Itoa(a)
    return sum,str
    }

    func main() {
    cd,str := add(100,200)
    fmt.Println("cd值为:",cd,str)
    }

    输出:cd值为: 300 100

    如果一个函数有多个返回值而你只想要其中的一个或几个,那么你不想要的返回值可以用下划线:_ 替代,也就是匿名变量

    eg:
    cd, str := add(100,200)
    此时不想要str 则改为:
    cd, _ := add(100,200)
  • 变量的作用域

    1
    2
    3
    4
    5
    6
    Go语言变量再三个地方声明:
    1. 函数内——局部变量
    2. 函数外——全局变量
    3. 函数中——形式参数

    与java定义类似不多解释
  • Go 语言指针

    • 默认值 nil,没有 NULL 常量。
    • 操作符 “&” (取地址符) 取变量地址,”*” (取值符)透过指针访问目标对象。
    • 不支持指针运算,不支持 “->” 运算符,直接用 “.” 访问目标成员。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    Go 支持指针。指针是保存值的地址的地方。 一个指针用 * 定义 
    指针声明:

    var name *类型

    package main

    var ip *int /* 指向整型*/ //声明一个int值得指针变量
    var fp *float32 /* 指向浮点型 */
    var sp *string /* 指向字符串类型 */
    func main() {

    }

    根据数据类型定义指针。 例:

    var ap *int
    上面的 ap 是指向整数类型的指针。& 运算符可用于获取变量的地址。

    a := 12
    ap = &a
    可以使用 * 运算符访问指针指向的值:

    fmt.Println(*ap)
    // => 12

    如何使用指针?

    指针使用流程:
    定义指针变量。
    为指针变量赋值。
    访问指针变量中指向地址的值。
    在指针类型前面加上 * 号(前缀)来获取指针所指向的内容。
  • 举个栗子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package main

import "fmt"

func main() {
var a int = 20 /* 声明实际变量 */
var ip *int /* 声明指针变量 */

ip = &a /* 指针变量的存储地址 */

fmt.Printf("a 变量的地址是: %x\n", &a)

/* 指针变量的存储地址 */
fmt.Printf("ip 变量的存储地址: %x\n", ip)

/* 使用指针访问值 */
fmt.Printf("*ip 变量的值: %d\n", *ip)
}
输出结果:

a 变量的地址是: c420012058
ip 变量的存储地址: c420012058
*ip 变量的值: 20


在将结构体作为参数传递或者为已定义类型声明方法时,通常首选指针。

传递值时,实际复制的值意味着更多的内存
传递指针后,函数更改的值将反映在方法 / 函数调用者中。
例子:
func increment(i *int) {
*i++
}
func main() {
i := 10
increment(&i)
fmt.Println(i)
}
//=> 11

上面那个栗子表示将i 用指针的形式再函数中加1,更改了i本身的值
  • 直接用指针访问目标对象成员:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    直接用指针访问目标对象成员:

    package main

    import (
    "fmt"
    )

    func main() {
    type data struct{ a int }

    var d = data{1234}
    var p *data

    p = &d
    fmt.Printf("%p, %v\n", p, p.a) // 直接用指针访问目标对象成员,无须转换。
    }
    输出结果:

    0xc420012058, 1234

    这种 .a 的形式有点类似于java中对象.变量的感觉,很熟悉,这样理解会方便一些

    注意:
    1. 不能对指针做加减法等运算。
    2. 可以在 unsafe.Pointer 和任意类型指针间进 转换。
    3. 将 Pointer 转换成 uintptr,可变相实现指针运算。

Go 空指针 nil

  • 当一个指针被定义后没有分配到任何变量时,它的值为 nil。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    nil 指针也称为空指针。

    nil在概念上和其它语言的null、None、nil、NULL一样,都指代零值或空值。

    一个指针变量通常缩写为 ptr 即 Pointer。

    实例:

    package main

    import "fmt"

    func main() {
    var ptr *int
    /* %x 指十六进制,小写字母,每字节两个字符*/
    fmt.Printf("ptr 的值为 : %x\n", ptr)
    }
    输出结果:

    ptr 的值为 : 0
  • 空指针判断:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    package main

    import (
    "fmt"
    )

    func main() {
    var ptr1 *int
    var i int = 1
    ptr2 := &i
    if ptr1 == nil {
    fmt.Println("prt1 是空指针")
    }
    if ptr2 != nil {
    fmt.Println("prt2 不是空指针 值为:")
    }
    }
    输出结果:

    prt1 是空指针
    prt2 不是空指针


    指针记录到这里我稍微总结一下:

    和C语言中指针类似,存储的是变量的地址值,我们无法直接给指针变量赋值
    但是我们先定义一个变量之后将其地址取出: 如何取? 用 & 取 &变量
    取出后我们把将要赋值的指针地址指向这个变量 ptr = &变量
    这样就实现了给指针赋值 之后 *ptr 就可取出指针的值
    请大家记住这个步骤:
    
    1. 指针声明格式如下:
    
    var name *类型
    
    2. 如何使用指针?
    
    指针使用流程:
    定义指针变量。
    为指针变量赋值。
    访问指针变量中指向地址的值。
    在指针类型前面加上 * 号(前缀)来获取指针所指向的内容。
    

Go 指针数组

  • 声明指针数组

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    var ptr [MAX]*int;
    ptr 为整型指针数组。因此每个元素都指向了一个值。以下实例的三个整数将存储在指针数组中:

    package main

    import "fmt"

    const MAX int = 3

    func main() {
    a := []int{9, 99, 999}
    var i int
    var ptr [MAX]*int

    for i = 0; i < MAX; i++ {
    ptr[i] = &a[i] /* 整数地址赋值给指针数组 */
    }

    for i = 0; i < MAX; i++ {
    fmt.Printf("a[%d] = %d\n", i, *ptr[i])
    }
    }
    输出结果:

    a[0] = 9
    a[1] = 99
    a[2] = 999

    如果一个指针变量存放的又是另一个指针变量的地址,则称这个指针变量为指向指针的指针变量。
    当定义一个指向指针的指针变量时,第一个指针存放第二个指针的地址,第二个指针存放变量的地址:

    指向指针的指针变量声明格式如下:

    var ptr **int
    以上指向指针的指针变量为整型。
    访问指向指针的指针变量值需要使用两个 * 号,如下所示:

    package main

    import "fmt"

    func main() {

    var a int
    var ptr *int
    var pptr **int

    a = 3000

    /* 指针 ptr 地址 */
    ptr = &a

    /* 指向指针 ptr 地址 */
    pptr = &ptr

    /* 获取 pptr 的值 */
    fmt.Printf("变量 a = %d\n", a)
    fmt.Printf("指针变量 *ptr = %d\n", *ptr)
    fmt.Printf("指向指针的指针变量 **pptr = %d\n", **pptr)
    }

    输出结果:

    变量 a = 3000
    指针变量 *ptr = 3000
    指向指针的指针变量 **pptr = 3000

请关注我的个人博客

 评论


博客内容遵循 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 协议

本站使用 Material X 作为主题 , 总访问量为 次 。
Copyright 2018-2019 YMLiang'BLOG   |   京ICP备 - 19039949  |  载入天数...载入时分秒...