✍ 个人博客: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)。
- 缺省格式和类型
- 整形(缩进、进制类型、正负符号)
- 字符(有引号、Unicode)
Value:65(Unicode letter A)
- 浮点(缩进、精度、科学计数)
Value:123.456
- 字符串/字节 silce(引号、缩进、16 进制)
Value:“cafe”
- 案例
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)