go 语言入门——基础数据类型(二)

一、布尔型(bool)
一个bool(布尔型 )的值只有两种:true和false。一般作为if或for(在Go语言中,为了精简循环语句,所以只有for而没有while等其他语句)的判断标准,也是比较符号(>、==等)的结果。

bool型可以和&&(AND)和||(OR)操作符相结合,并会有短路行为(当已经可以判断真假时,就会直接返回结果,而不会把后面的运算都计算)。

需要注意,&&的优先级大于||

bool型可以在if语句中和数字转换,0等价于false,1(也可以是>0的数)等价于true

二、字符串 string
一个字符串是一个不可改变的字节序列。字符串可以包含任意的数据,包括byte值0,但是通常是用来包含人类可读的文本。这里需要注意,Go语言中,字符串是不可以改变的,而一般的C系列,string类型可以近似的看成一个字符的数组,所以可以直接通过下标进行字符的修改,但是Go语言并不能这样操作。Go语言中string类型还有内置的len函数,返回字符串的字节数目(len(s)),可以用下标返回字节的值s[i].

s := "hello world" 
fmt.Println(len(s))     // "12"
fmt.Println(s[0], s[7]) // "104 119" ('h' and 'w'),这里需要注意,直接用fmt.Println打印某个字节,会得到对应的ASCII码的值
s[0] = 'L'              // compile error: cannot assign to s[0] ,Go语言不能改变string的值
c := s[len(s)]          // panic: index out of range,超过字符串范围会报错

Go语言和Python类似,也可以使用“:”用来进行切片操作,比如a[0:3]表示字符串a对第一个字符到第三个字符进行切片(如果a为"abcde",那么a[0:3]表示"abc")

//s为上面的"hello world"
fmt.Println(s[:5]) // "hello"
fmt.Println(s[7:]) // "world"
fmt.Println(s[:])  // "hello, world"

Go语言中可以用"+"操作符将两个字符串连接构造成一个新的字符串。同样,也可以使用+=符号,但是需要注意的是,+=并不是改变了字符串的值,而是创建了一个新的字符串,并将这个新的字符串赋给了原来的变量。Go语言中的字符串也可以进行比较操作(所有的比较运算符),比较通过逐个字符比较完成

fmt.Println("goodbye" + s[5:]) // "goodbye, world"
s += " !!!!"                   //s为"hello world !!!!"
s <  "w"                       //true,因为h的ASCII码值小于w,此时已经比较出了结果,不需要后续的操作

1、字符串面值
字符串值也可以用字符串面值方式编写,只要将一系列字节序列包含在双引号内即可:

"Hello, 世界"

因为Go语言源文件总是用UTF8编码,并且Go语言的文本字符串也以UTF8编码的方式处理,因此我们可以将Unicode码点也写到字符串面值中。
在一个双引号包含的字符串面值中,可以用以反斜杠\开头的转义序列插入任意的数据。下面的换行、回车和制表符等是常见的ASCII控制代码的转义方式:

\a      响铃
\b      退格
\f      换页
\n      换行
\r      回车
\t      制表符
\v      垂直制表符
\'      单引号 (只用在 '\'' 形式的rune符号面值中)
\"      双引号 (只用在 "..." 形式的字符串面值中)
\\      反斜杠

2、字符串的相关函数
标准库中有四个包对字符串处理尤为重要:bytes(将在下一小节单独记录)、strings、strconv和unicode包。
strings包提供了许多如字符串的查询、替换、比较、截断、拆分和合并等功能。

s := "Hello,World!!!!!"

//Count计算字符串sep在s中的非重叠个数
//func Count(s, sep string) int
n := strings.Count(s, "!")  //n的值为5
n := strings.Count(s, "!!") //n的值为2

//Contains判断字符串s中是否包含子串substr
//func Contains(s, substr string) bool
strings.Contains(s, "Hello")  //结果为true

//ContainsAny判断字符串s中是否包含chars中的任何一个字符
//func ContainsAny(s, chars string) bool
strings.ContainsAny(s, "HJK")  //结果为true

//ContainsRune判断字符串s中是否包含字符r
//Go语言的单引号一般用来表示「rune literal」,即码点字面量
//func ContainsRune(s string, r rune) bool
strings.ContainsRune(s, 'H')  //结果为true

//Index返回子串sep在字符串s中第一次出现的位置,如果找不到,则返回-1
//func Index(s, sep string) int
n := strings.Index(s, "W") //n的值为6

//LastIndex返回子串sep在字符串s中最后一次出现的位置,如果找不到,则返回-1
//func LastIndex(s, sep string) int
n := strings.LastIndex(s, "l")   //n的值为9

//IndexRune返回字符r在字符串s中第一次出现的位置,如果找不到,则返回-1
//func IndexRune(s string, r rune) int
n := strings.IndexRune(s, 'W')   //n的值为6

//IndexAny返回字符串chars中的任何一个字符在字符串s中第一次出现的位置,如果找不到,则返回-1
//func IndexAny(s, chars string) int
n := strings.IndexAny(s, "rd")  //n的值为8

//LastIndexAny返回字符串chars中的任何一个字符在字符串s中最后一次出现的位置如果找不到,则返回-1
//func LastIndexAny(s, chars string) int
n :=  strings.LastIndexAny(s, "rd")  //n的值为10

//Split以sep为分隔符,将s切分成多个子切片:
//func Split(s, sep string) []string
sub_s := strings.Split(s, ",")  //sub_s为[Hello World!!!!!],即sub_s[0]为"Hello", sub_s[1]为"World!!!!!"

//Join将a中的子串连接成一个字符串,用sep分隔
//func Join(a []string, sep string) string
ss := []string{"Monday", "Tuesday", "Wednesday"}
strings.Join(ss, "|")   //结果为Monday|Tuesday|Wednesday

//HasPrefix判断字符串s是否以prefix开头
//func HasPrefix(s, prefix string) bool
strings.HasPrefix(s, "He")  // 结果为true

//HasSuffix判断字符串s是否以prefix结尾:true
//func HasSuffix(s, suffix string) bool
strings.HasSuffix(s, "!!")

//Repeat将count个字符串s连接成一个新的字符串
//func Repeat(s string, count int) string
strings.Repeat(s, 2)

//ToUpper将s中的所有字符修改为其大写格式:HELLO,WORLD!!!!!
//func ToUpper(s string) string
strings.ToUpper(s)

//ToLower将s中的所有字符修改为其小写格式:hello,world!!!!!
//func ToLower(s string) string
strings.ToLower(s)

//Replace返回s的副本,并将副本中的old字符串替换为new字符串
//替换次数为 n 次,如果 n 为 -1,则全部替换
//func Replace(s, old, new string, n int) string
strings.Replace(s, "!", "|", -1)

//EqualFold判断s和t是否相等。忽略大小写,同时它还会对特殊字符进行转换:true
//比如将“ϕ”转换为“Φ”、将“DŽ”转换为“Dž”等,然后再进行比较
 //func EqualFold(s, t string) bool
s1 := "Hello 世界! ϕ DŽ"
s2 := "hello 世界! Φ Dž"
strings.EqualFold(s1, s2)

//Len返回r.i之后的所有数据的字节长度:16
//func (r *Reader) Len() int
r.Len()

//Replace 返回对 s 进行“查找和替换”后的结果
//Replace 使用的是 Boyer-Moore 算法,速度很快
//func (r *Replacer) Replace(s string) string
srp := strings.NewReplacer("Hello", "你好", "World", "世界", "!", "!")
s = "Hello World!Hello World!hello world!"
rst := srp.Replace(s)
fmt.Print(rst) //你好 世界!你好 世界!hello world!

上述函数均参考”http://static.markbest.site/blog/93.html“,还有一些方法没有罗列,如需要,可直接在该网站上查询。

strconv包提供了布尔型、整型数、浮点数和对应字符串的相互转换,还提供了双引号转义相关的转换。

//Atoi将string转成int,Itoa将int转成string
fmt.Println(strconv.Atoi("123"))  // 123, nil
fmt.Println(strconv.Atoi("123a")) // 0, strconv.ParseInt: parsing "123a": invalid syntax
fmt.Println(strconv.Itoa(123))    // 123

//format和parse是两组相反的方法,用于string和其它类型之间的相互转化。相关方法有:
fmt.Println(strconv.FormatBool(true))                 // true
fmt.Println(strconv.FormatFloat(3.1415, 'E', -1, 64)) // 3.1415E+00
fmt.Println(strconv.FormatInt(-42, 16))               // -2a
fmt.Println(strconv.FormatUint(42, 16))               // 2a

fmt.Println(strconv.ParseBool("tRue"))        // true 
fmt.Println(strconv.ParseFloat("3.1415", 32)) // 3.1414999961853027 
fmt.Println(strconv.ParseFloat("3.1415", 64)) // 3.1415 
fmt.Println(strconv.ParseInt("-42", 10, 32))  // -42 
fmt.Println(strconv.ParseInt("11011", 2, 32)) // 27 
fmt.Println(strconv.ParseInt("0xff", 0, 32))  // 255 
fmt.Println(strconv.ParseUint("42", 16, 32))  // 66 

上述函数均参考”https://syaning.github.io/go-pkgs/strconv/“,还有一些方法没有罗列,如需要,可直接在该网站上查询。

unicode包提供了IsDigit、IsLetter、IsUpper和IsLower等类似功能,它们用于给字符分类。详细功能,可参考”https://studygolang.com/articles/4358“。

三、byte数组
一个[]byte(s)转换是分配了一个新的字节数组用于保存字符串数据的拷贝,然后引用这个底层的字节数组。可以类比C语言和C++中的char[]数组,在此数组中,可以更多的进行其他操作,比如更改其中的某个元素。
其基本方法和strings包类似,具体参考”https://syaning.github.io/go-pkgs/bytes”

四、常量
常量表达式的值在编译期计算,而不是在运行期。每种常量的潜在类型都是基础类型:boolean、string或数字。常量一旦初始化,将不可再一次更改。

const pi = 3.14159 
//声明多个常量
const (
    e  = 2.71828182845904523536028747135266249775724709369995957496696763
    pi = 3.14159265358979323846264338327950288419716939937510582097494459
)

常量间的所有算术运算、逻辑运算和比较运算的结果也是常量,对常量的类型转换操作或以下函数调用都是返回常量结果:len、cap、real、imag、complex和unsafe.Sizeof

1、iota常量生成器
常量声明可以使用iota常量生成器初始化,它用于生成一组以相似规则初始化的常量,但是不用每行都写一遍初始化表达式。在一个const声明语句中,在第一个声明的常量所在的行,iota将会被置为0,然后在每一个有常量声明的行加一。

type Weekday int
const (
    Sunday Weekday = iota
    Monday
    Tuesday
    Wednesday
    Thursday
    Friday
    Saturday
)

周日将对应0,周一为1,如此等等。
我们同样可以再复杂的常量表达式中使用iota,下面是来自net包的例子,用于给一个无符号整数的最低5bit的每个bit指定一个名字:

type Flags uint

const (
    FlagUp Flags = 1 << iota // FlagUp = 1 <<0       is up     
    FlagBroadcast            // FlagBroadcast  = 1<<1  supports broadcast access capability
    FlagLoopback             // FlagLoopback= 1<<2    is a loopback interface
    FlagPointToPoint         // FlagPointToPoint= 1<<3    belongs to a point-to-point link
    FlagMulticast            //FlagMulticast= 1<<4  supports multicast access capability
)

2、无类型常量
Go语言中可以设置无明确的基础类型的常量,编译器为这些没有明确基础类型的数字常量提供比基础类型更高精度的算术运算。这里有六种未明确类型的常量类型,分别是无类型的布尔型、无类型的整数、无类型的字符、无类型的浮点数、无类型的复数、无类型的字符串。
例如,math.Pi就是一个无类型浮点数常量,但是也可以被转换为float64

const Pi64 float64 = math.Pi

你可能感兴趣的:(go 语言入门——基础数据类型(二))