【新人系列】Golang 入门(二):基本数据类型

发布于:2025-03-04 ⋅ 阅读:(15) ⋅ 点赞:(0)

✍ 个人博客:https://blog.csdn.net/Newin2020?type=blog
📝 专栏地址:https://blog.csdn.net/newin2020/category_12898955.html
📣 专栏定位:为 0 基础刚入门 Golang 的小伙伴提供详细的讲解,也欢迎大佬们一起交流~
📚 专栏简介:在这个专栏,我将带着大家从 0 开始入门 Golang 的学习。在这个 Golang 的新人系列专栏下,将会总结 Golang 入门基础的一些知识点,并由浅入深的学习这些知识点,方便大家快速入门学习~
❤️ 如果有收获的话,欢迎点赞 👍 收藏 📁 关注,您的支持就是我创作的最大动力 💪

在这里插入图片描述

1. bool 类型

布尔类型的值只可以是常量 true 或者 false,比如:var b bool = true。

2. 数值类型

在这里插入图片描述

注意:
byte 和 rune 主要是用于存储字符,byte 存储的范围更小,rune 存储的范围更大,可以包括中文。

3. string 类型

3.1 底层存储原理

var str string = "hello"

go 语言和 c 语言对于字符串结尾的判定条件有所不同,c 语言会认为在结尾处加上 \0 就代表这个字符串的结束。但是这就会限制内容中不能再出现 \0,如果出现就会发生不可预估的后果。

因此,在 go 语言中并没有采用这种方式,而是在起始地址后边,多存了一个长度。

在这里插入图片描述

注意:
在起始地址后存的长度并不是表示字符个数,而是表示字节个数。

3.2 常用操作

package main

import (
    "fmt"
    "strings"
)

func main() {
    //打印字符串字符长度
    fmt.Println(len("hello"))    // 5
    b := "你好"
    fmt.Println(len(b))    // 6
    
    //是否包含
    name := "golang - good"
    fmt.Println(strings.Contains(name, "go"))    // true
    
    //出现次数
    fmt.Println(strings.Count(name, "o")    // 3
    
    //分割字符串
    fmt.Println(strings.Split(name, "-"))    // [golang   good]
    
    //字符串是否包含前缀,是否包含后缀
    fmt.Println(strings.HasPrefix(name, "gol"))    // true
    fmt.Println(strings.HasSuffix(name, "ood"))    // true
    
    //查找子串出现的位置
    fmt.Println(strings.Index(name, "go"))    // 0
    
    //重复打印
    fmt.Println(strings.Repeat("hello", 2))    // hellohello
    
    //子串替换
    fmt.Println(strings.Replace(name, "go", "java", 1))    // javalang - good
    
    //大小写转换
    fmt.Println(strings.ToLower("GO"))    // go
    fmt.Println(strings.ToUpper("java"))    // JAVA
    
    //去掉字符串两头的特殊字符
    fmt.Println(strings.Trim("#hello #go#", "#"))    // hello #go
}

3.3 数字解析

在 go 语言中,关于字符串和数字类型之间的转换的函数都在 strconv 这个包下。

package main

import (
    "fmt"
    "strconv"
)

func main() {
    f, _ := strconv.ParseFloat("1.234", 64)     // 解析为float64类型
    fmt.Println(f)  // 1.234

    n1, _ := strconv.ParseInt("111", 10, 64)    // 以十进制解析为int64类型
    fmt.Println(n1) // 111

    n2, _ := strconv.ParseInt("0x100", 0, 64)   // 进制参数为0,表示根据字符串的前缀自动判断进制,这里0x表示十六进制,所以解析为int64类型
    fmt.Println(n2) // 4096

    n3, _ := strconv.Atoi("123")    // 解析为int类型
    fmt.Println(n3) // 123

    n4, err := strconv.Atoi("AAA")
    fmt.Println(n4, err)    // 0 strconv.Atoi: parsing "AAA": invalid syntax
}

3.4 格式化输出

注意:
以字母 f 结尾的格式化函数,如 log.Printf 和 fmt.Errorf,都采用 fmt.Printf 的格式化准则。而以 ln 结尾的格式化函数,则遵循 Println 的方式,以跟 %v 差不多的方式格式化参数,并在最后添加一个换行符(译注:后缀 f 指 format,ln 指 line)。

  1. 缺省格式和类型

在这里插入图片描述

  1. 整形(缩进、进制类型、正负符号)

在这里插入图片描述

  1. 字符(有引号、Unicode)

Value:65(Unicode letter A)

在这里插入图片描述

  1. 浮点(缩进、精度、科学计数)

Value:123.456

在这里插入图片描述

  1. 字符串/字节 silce(引号、缩进、16 进制)

Value:“cafe”

在这里插入图片描述

  1. 案例
package main

import "fmt"

type point struct {
    x, y int
}

func main() {
    s := "hello"
    n := 123
    p := point{1, 2}
    fmt.Println(s, n)   // hello 123
    fmt.Println(p)      // {1 2}

    fmt.Printf("s=%v\n", s)     // s=hello
    fmt.Printf("n=%v\n", n)     // n=123
    fmt.Printf("p=%v\n", p)     // p={1 2}
    fmt.Printf("p=%+v\n", p)    // p={x:1 y:2}
    fmt.Printf("p=%#v\n", p)    // p=main.point{x:1, y:2}

    f := 3.141592653589793
    fmt.Println(f)              // 3.141592653589793
    fmt.Printf("%.2f\n", f)     // 3.14
}

3.5 只读特性

下标访问字符串:

str := "golang"
fmt.Println("%c\n", s1[2])    //可以执行
//s1[2] = 'e'    //错误

注意:
go 语言中不能用下标直接去修改字符串内容,但是可以用来访问。
原因是 go 认为上面这样的字符串是不会被修改的,所以会把这样定义的字符串内容分配到只读内存段。

如果想修改字符串内容的话,可以转化成 slice,但是可能会同时修改底层字符串的内容。

如果想脱离这个只读的限制,并且想修改时不会影响到底层字符串的内容。那么可以转换成字节 slice,这样就会为 slice 变量重新分配一段内存,同时会也会拷贝原来字符串的内容。

这是因为字符串在Go语言中是不可变的,而字节slice是可变的。因此,如果要修改字符串的内容,需要先将其转换成字节slice,然后再进行修改。

byteStr := ([]byte)(s1)
byteStr[2] = 'x'
fmt.Printf("%c\n", byteStr[2])    //x

举个具体点的例子:

package main

import(
    "fmt"
    "unicode/utf8"
)

func main() {
    s := "go语言"
    arr := []byte(s)
    fmt.Println(arr)              //[103 111 232 175 173 232 168 128]
    fmt.Println(arr[2], s[2])     //232 232
    arr[2] = 9
    //s[2] = 9 //字符串不能修改
    
    fmt.Println(len(s), len(arr)) //8 8
    
    brr := []rune(s) // 一个汉字是一个 rune
    fmt.Println(brr)    //[103 111 35821 35328]
    fmt.Printf("%d %d %s %s\n", brr[2], s[2], string(brr[2]), string(s[2]))    //35821 232 语 è
    fmt.Println(utf8.RuneCountInString(s))    //4(查看 string 中有几个 rune)
}

3.6 高性能字符串拼接

username := "张三"
age := 24
address := "北京"
mobile := "18989898989"

性能要求不高,平时一般采用:

userMsg := fmt.Sprinf("用户名:%s,年龄:%d,地址:%s,电话:%s", username, age, address, mobile)

性能要求高:

var builder string.Builder
builder.WriteString("用户名:")
builder.WriteString(username)
builder.WriteString(",年龄:")
builder.WriteString(strconv.Itoa(age))
builder.WriteString(",地址:")
builder.WriteString(address)
builder.WriteString(",电话:")
builder.WriteString(mobile)
re := builder.String()
fmt.Println(re)