go语言基础(三):字符串、map、结构体、指针

字符串
字符串的定义
package main

import "fmt"

func main()  {
    //hello world
	var str string = "hello world"
	fmt.Println(str)
}
字符串的操作
package main

import (
	"fmt"
	"strconv"
	"strings"
)

func main()  {
    //hello world
	var str string = "hello world"
	fmt.Println(str)

	// Contains
	fmt.Println(strings.Contains(str,"hello"))

	// Index
	fmt.Println(strings.Index(str,"world"))

    // Split
	fmt.Println(strings.Split(str,"lo"))

    // Format : 将其他类型的数据 转换为字符串
    var str2 string= strconv.FormatBool(true)
    fmt.Println(str2)

    // Itoa 整型转字符串
    var str3 string
    str3 = strconv.Itoa(666)
    fmt.Println(str3)

    // Parse 将字符串转换为其他类型
    if flag,err := strconv.ParseBool("true");err == nil{
		fmt.Println(flag)
	}else {
		fmt.Println(err)
	}
}
Map
什么是Map

GO语言中的Map,也称为字典,是有键和值构成的。

Map的定义
	var a map[int]int

定义字典结构使用map关键字,[ ]中指定的是键(key)的类型,后面紧跟着的是值的类型。

键的类型,必须是支持==和!=操作符的类型,切片、函数以及包含切片的结构类型不能作为字典的键,使用这些类型会造成编译错误。

注意:字典中不能使用cap函数,只能使用len( )函数。len( )函数返回map拥有的键值对的数量。

定义一个map:

package main

import "fmt"

func main()  {
	a:= make(map[string] string)
    fmt.Println(a,len(a))

    a["test"] = "张三"
    a["devops"] = "李四"
	fmt.Println(a,len(a))

    b:= map[int]string{1:"mark",2:"picaso",3:"joe"}
	fmt.Println(b,len(b))

    //打印map的值
    for k,v := range b {
    	fmt.Println("key = ",k)
		fmt.Println("value = ",v)
	}
}
结构体
结构体的定义
type Student struct {
	 id int
	 name string
	 sex byte // 字符类型
	 age int
     address string
}

type 后面跟着的是结构体的名字Student, struct表示定义的是一个结构体。

大括号中是结构体的成员,注意在定义结构体成员时,不要加var.

通过以上的定义,大家能够感觉出,通过结构体来定义复杂的数据结构,非常清晰。

结构体定义完成后,可以进行初始化。

结构体的初始化

package main

import "fmt"

type Student struct {
	 id int
	 name string
	 sex byte // 字符类型
	 age int
     address string
}

func main()  {
	// 顺序初始化,每个成员必须初始化
  mark := Student{1,"mark",'m',25,"长沙"}
  fmt.Println(mark)

  // 指定成员初始化,没有初始化的成员,自动赋值为0
  leo:= Student{name: "leo"}
  fmt.Println(leo)
}

输出如下:

{1 mark 109 25 长沙}
{0 leo 0 0 }
比较与赋值

两个结构体可以使用 == 或 != 运算符进行比较,但不支持 > 或 <。

  mark := Student{1,"mark",'m',25,"长沙"}
  mark2 := Student{1,"mark",'m',25,"长沙"}
  fmt.Println(mark == mark2)

输出如下:

true
结构体数组
package main

import "fmt"

type Student struct {
	 id int
	 name string
	 sex byte // 字符类型
	 age int
     address string
}

func main()  {
  marks:= []Student{{name: "mark",age: 18},{name: "mask",age: 20}}
  fmt.Println(marks)
}

输出如下:

[{0 mark 0 18 } {0 mask 0 20 }]
结构体做函数参数
package main

import "fmt"

type Student struct {
	 id int
	 name string
	 sex byte // 字符类型
	 age int
     address string
}

func main()  {
  marks:= Student{name: "mark",age: 18}
  testStruct(marks)
}

func testStruct(student Student)  {
	fmt.Println(student)
}

结构体作为函数参数进行传递,是值传递!

指针
什么是指针

一个指针变量指向了一个值的内存地址。

类似于变量和常量,在使用指针前你需要声明指针。指针声明格式如下:

var var_name *var-type

var-type 为指针类型,var_name 为指针变量名,* 号用于指定变量是作为一个指针。以下是有效的指针声明:

var ip *int        /* 指向整型*/
var fp *float32    /* 指向浮点型 */
指针的定义
package main

import "fmt"

func main() {
	a := 100
	var p *int
	p = &a
	fmt.Printf("a的内存地址为:%p ,值为:%d\n", p, *p)
}

输出如下:

a的内存地址为:0xc0000ac058 ,值为:100

指针变量p的定义是通过 *这个符号来定义,指针变量p的类型为*int, 表示存储的是一个整型变量的地址。

如果指针变量p存储的是一个字符串类型变量的地址,那么指针变量p的类型为*string

**p=&a 😗*该行代码的意思是,将变量a的地址取出来,并且赋值给指针变量p.也就是指针变量p指向了变量i的存储单元。

大家可以思考一个问题:

既然指针变量p指向了变量a的存储单元,那么是否可以通过指针变量p,来操作变量i中存储的数据?

答案是可以的,具体操作方式如下: *p = 66

package main

import "fmt"

func main() {
	a := 100
	var p *int
	p = &a
	*p = 66
	fmt.Printf("a的值为:%d\n", a)
}

输出如下:

a的值为:66
指针作为函数参数

指针也可以作为函数参数,那么指针作为函数参数在进行传递的时候,是值传递还是引用传递呢?

package main

import "fmt"

func main() {
	a := 100
	var p *int
	p = &a
	fmt.Printf("a的值为:%d\n", a)
	testPoint(p)
	fmt.Printf("调用后,a的值为:%d\n", a)

}

func testPoint(p *int) {
	*p = 666
}

输出如下:

a的值为:100
调用后,a的值为:666

通过以上案例证实,指针作为参数进行传递时,为引用传递,也就是传递的地址。

数组指针

前面在讲解数组的时候,我们用数组作为函数参数,但是数组作为参数进行传递是值传递,如果想引用传递,可以使用数组指针。具体使用方式如下:

package main

import "fmt"

func main() {
	a := [5]int{1, 2, 3, 4, 5}
	testPoint(&a)
	fmt.Println(a)
}

func testPoint(p *[5]int) {
	// *p 的值 等于数组a的值
	fmt.Println(*p)
	(*p)[0] = 666
}

输出如下:

[1 2 3 4 5]
[666 2 3 4 5]

指针p,指向了数组a,对指针p的操作实际上是对数组a的操作,所以如果直接执行如下语句:fmt.Println(*p),会输出数组a中的值。也可以通过*p结合下标将对应的值取出来进行修改。最终在main函数中输出数组a,发现其元素也已经修改。

指针数组

上一小节,讲解到的是数组指针,也就是让一个指针指向数组 ,然后可以通过该指针来操作数组。还有一个概念叫指针数组,这两个概念很容混淆,指针数组指的是一个数组中存储的都是指针(也就是地址)。也就是一个存储了地址的数组。

下面通过一个案例,看一下指针数组的应用:

package main

import "fmt"

func main() {
	var p [2]*int
	i, j := 10, 20
	p[0], p[1] = &i, &j
	fmt.Println(p, *p[0], *p[1])
}

输出如下:

[0xc0000ac058 0xc0000ac070] 10 20

指针数组的定义方式,与数组指针定义方式是不一样的,注意指针数组是将“*”放在了下标的后面。

由于指针数组存储的都是地址,所以将变量i,与变量j的地址赋值给了指针数组p。

最后输出指针数组p中存储的地址和对应的值。

结构体指针变量

我们前面定义了指针指向了数组,解决了数组引用传递的问题。那么指针是否可以指向结构体,也能够解决结构体引用传递的问题呢?完全可以。

import "fmt"

type Teacher struct {
	name string
	age  int
}

func main() {
	p := &Teacher{name: "mark", age: 25}
	p.age = 20
	fmt.Println(*p)
}

ckage main

import “fmt”

func main() {
a := 100
var p *int
p = &a
fmt.Printf(“a的值为:%d\n”, a)
testPoint§
fmt.Printf(“调用后,a的值为:%d\n”, a)

}

func testPoint(p *int) {
*p = 666
}


输出如下:

```go
a的值为:100
调用后,a的值为:666

通过以上案例证实,指针作为参数进行传递时,为引用传递,也就是传递的地址。

数组指针

前面在讲解数组的时候,我们用数组作为函数参数,但是数组作为参数进行传递是值传递,如果想引用传递,可以使用数组指针。具体使用方式如下:

package main

import "fmt"

func main() {
	a := [5]int{1, 2, 3, 4, 5}
	testPoint(&a)
	fmt.Println(a)
}

func testPoint(p *[5]int) {
	// *p 的值 等于数组a的值
	fmt.Println(*p)
	(*p)[0] = 666
}

输出如下:

[1 2 3 4 5]
[666 2 3 4 5]

指针p,指向了数组a,对指针p的操作实际上是对数组a的操作,所以如果直接执行如下语句:fmt.Println(*p),会输出数组a中的值。也可以通过*p结合下标将对应的值取出来进行修改。最终在main函数中输出数组a,发现其元素也已经修改。

指针数组

上一小节,讲解到的是数组指针,也就是让一个指针指向数组 ,然后可以通过该指针来操作数组。还有一个概念叫指针数组,这两个概念很容混淆,指针数组指的是一个数组中存储的都是指针(也就是地址)。也就是一个存储了地址的数组。

下面通过一个案例,看一下指针数组的应用:

package main

import "fmt"

func main() {
	var p [2]*int
	i, j := 10, 20
	p[0], p[1] = &i, &j
	fmt.Println(p, *p[0], *p[1])
}

输出如下:

[0xc0000ac058 0xc0000ac070] 10 20

指针数组的定义方式,与数组指针定义方式是不一样的,注意指针数组是将“*”放在了下标的后面。

由于指针数组存储的都是地址,所以将变量i,与变量j的地址赋值给了指针数组p。

最后输出指针数组p中存储的地址和对应的值。

结构体指针变量

我们前面定义了指针指向了数组,解决了数组引用传递的问题。那么指针是否可以指向结构体,也能够解决结构体引用传递的问题呢?完全可以。

import "fmt"

type Teacher struct {
	name string
	age  int
}

func main() {
	p := &Teacher{name: "mark", age: 25}
	p.age = 20
	fmt.Println(*p)
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
结合视频效果更好 https://www.bilibili.com/video/av81167448?p=189 1. 初识Go语言 1 1.1 Go语言介绍 1 1.1.1 Go语言是什么 1 1.1.2 Go语言优势 1 1.1.3 Go适合用来做什么 2 1.2 环境搭建 2 1.2.1 安装和设置 2 1.2.2 标准命令概述 2 1.2.3 学习资料 3 1.3 第一个Go程序 3 1.3.1 Hello Go 3 1.3.2 代码分析 3 1.3.3 命令行运行程序 4 2. 基础类型 4 2.1 命名 4 2.2 变量 5 2.2.1 变量声明 5 2.2.2 变量初始化 6 2.2.3 变量赋值 6 2.2.4 匿名变量 6 2.3 常量 7 2.3.1 字面常量(常量值) 7 2.3.2 常量定义 8 2.3.3 iota枚举 8 2.4 基础数据类型 10 2.4.1 分类 10 2.4.2 布尔类型 11 2.4.3 整型 11 2.4.4 浮点型 11 2.4.5 字符类型 11 2.4.6 字符串 12 2.4.7 复数类型 12 2.5 fmt包的格式化输出输入 13 2.5.1 格式说明 13 2.5.2 输出 14 2.5.3 输人 14 2.6 类型转换 15 2.7 类型别名 15 3. 运算符 15 3.1 算术运算符 15 3.2 关系运算符 16 3.3 逻辑运算符 16 3.4 位运算符 16 3.5 赋值运算符 17 3.6 其他运算符 17 3.7 运算符优先级 17 4. 流程控制 18 4.1 选择结构 18 4.1.1 if语句 18 4.1.2 switch语句 19 4.2 循环语句 20 4.2.1 for 20 4.2.2 range 20 4.3 跳转语句 21 4.3.1 break和continue 21 4.3.2 goto 21 5. 函数 22 5.1 定义格式 22 5.2 自定义函数 22 5.2.1 无参无返回值 22 5.2.2 有参无返回值 23 5.2.3 无参有返回值 24 5.2.4 有参有返回值 25 5.3 递归函数 26 5.4 函数类型 27 5.5 匿名函数与闭包 27 5.6 延迟调用defer 30 5.6.1 defer作用 30 5.6.2 多个defer执行顺序 30 5.6.3 defer和匿名函数结合使用 31 5.7 获取命令行参数 31 5.8 作用域 32 5.8.1 局部变量 32 5.8.2 全局变量 33 5.8.3 不同作用域同名变量 33 6. 工程管理 34 6.1 工作区 34 6.1.1 工作区介绍 34 6.1.2 GOPATH设置 35 6.2 包 35 6.2.1 自定义包 35 6.2.2 main包 36 6.2.3 main函数和init函数 36 6.2.4 导入包 38 6.3 测试案例 40 6.3.1 测试代码 40 6.3.2 GOPATH设置 42 6.3.3 编译运行程序 43 6.3.4 go install的使用 43 7. 复合类型 45 7.1 分类 45 7.2 指针 45 7.2.1 基本操作 45 7.2.2 new函数 46 7.2.3 指针做函数参数 46 7.3 数组 47 7.3.1 概述 47 7.3.2 操作数组 47 7.3.3 在函数间传递数组 48 7.4 slice 49 7.4.1 概述 49 7.4.2 切片的创建和初始化 49 7.4.3 切片的操作 50 7.4.4 切片做函数参数 52 7.5 map 53 7.5.1 概述 53 7.5.2 创建和初始化 53 7.5.3 常用操作 54 7.5.4 map做函数参数 55 7.6 结构体 56 7.6.1 结构体类型 56 7.6.2 结构体初始化 57 7.6.3 结构体成员的使用 57 7.6.4 结构体比较 58 7.6.5 结构体作为函数参数 59 7.6.6 可见性 59 8. 面向对象编程 61 8.1 概述 61 8.2 匿名组合 61 8.2.1 匿名字段 61 8.2.2 初始化 62 8.2.3 成员的操作 62 8.2.4 同名字段 63 8.2.5 其它匿名字段 64 8.3 方法 65 8.3.1 概述 65 8.3.2 为类型添加方法 66 8.3.3 值语义和引用语义 67 8.3.4
在 Go 中,可以使用标准库中的 `encoding/json` 包将 JSON 字符串反序列化成对应的结构体或者 map 类型。对于一段复杂的 JSON 字符串,可以按照以下步骤进行反序列化操作: 1. 根据 JSON 字符串的格式定义一个对应的 Go 结构体类型,或者使用 map 类型接收 JSON 数据。 例如,如果 JSON 字符串的格式为 `{"name": "Tom", "age": 18, "address": {"city": "Beijing", "street": "Nanluoguxiang"}}`,则可以定义如下的 Go 结构体类型: ```go type Address struct { City string `json:"city"` Street string `json:"street"` } type Person struct { Name string `json:"name"` Age int `json:"age"` Address Address `json:"address"` } ``` 其中,`Address` 结构体嵌套在 `Person` 结构体中,用于描述 `Person` 的地址信息。 2. 将 JSON 字符串转换成字节数组(`[]byte`)。 例如,如果 JSON 字符串为 `{"name": "Tom", "age": 18, "address": {"city": "Beijing", "street": "Nanluoguxiang"}}`,则可以通过 `[]byte(jsonStr)` 将其转换成字节数组。 3. 调用 `json.Unmarshal` 函数将 JSON 字符串反序列化到 Go 结构体或者 map 类型中。 例如,可以按照以下方式调用 `json.Unmarshal` 函数进行反序列化操作: ```go var p Person err := json.Unmarshal([]byte(jsonStr), &p) if err != nil { // 处理反序列化失败的错误 } ``` 在调用 `json.Unmarshal` 函数时,第一个参数为要反序列化的 JSON 字符串所对应的字节数组,第二个参数为一个指向要反序列化到的 Go 结构体对象的指针或者 map 类型对象的指针。在函数执行成功后,Go 结构体对象 `p` 或者 map 类型对象就会被赋值为 JSON 字符串所对应的值。 需要注意的是,如果 JSON 字符串中的键值对与 Go 结构体中的字段不匹配,或者 JSON 字符串格式不正确,都有可能导致反序列化失败,此时需要进行错误处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一彡十

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值