您的位置:首页 > 编程语言 > Go语言

Go语言学习笔记 - 第三章 基本类型(The Go Programming Language)

2020-01-13 06:07 423 查看

第三章 基本类型

Go语言四大数据类型:基础类型、复合类型、引用类型和接口类型

  • 基础类型 数字、字符串和布尔型
  • 复合类型 数组和结构体
  • 引用类型 指针、切片、字典、函数、通道
  • 接口类型 抽象类型

3.1整型

划重点

  • int8
    int16
    int32
    int64
    int
  • uint8
    uint16
    uint32
    uint64
    uint
  • Unicode字符
    rune
    类型是和
    int32
    等价的类型,通常用于表示一个Unicode码点
  • byte
    uint8
    类型的等价类型,
    byte
    类型一般用于强调数值是一个原始的数据而不是一个小的整数
  • uintptr类型只有在底层编程是才需要,特别是Go语言和C语言函数库或操作系统接口相交互的地方
  • int
    当作
    int32
    类型的地方需要一个显式的类型转换操作,反之亦然,其他的也是,及时大小一致,但是需要显示转换
var apples int32 = 1
var oranges int16 = 2
var compote int = apples + oranges // compile error
  • 算术运算、逻辑运算和比较运算,优先级递减排序
* / % << >> & &^
+ - | ^
== != < <= > >=
&&
||
  • %
    取模运算符的符号和被取模数的符号总是一致的,因此
    -5%3
    -5%-3
    结果都是
    -2
  • 除法运算符
    /
    ,
    5.0/4.0
    的结果是
    1.25
    ,但是
    5/4
    的结果是
    1
  • 超出的高位的bit位部分将被丢弃。如果原始的数值是有符号类型,而且最左边的bit为是1的话,那么最终结果可能是负的
  • 比较运算符
== equal to
!= not equal to
< less than
<= less than or equal to
> greater than
>= greater than or equal to
  • bit位操作运算符
& 位运算 AND
| 位运算 OR
^ 位运算 XOR
&^ 位清空 (AND NOT)
<< 左移
>> 右移
  • 无符号数往往只有在位运算或其它特殊的运算场景才会使用,就像bit集合、分析二进制文件格式或者是哈希和加密操作等
  • 类型转换会造成精度的丢失,和C语言类似
  • fmt的使用技巧:
    Printf格式化字符串包含多个%参数时将会包含对应相同数量的额外操作数,但是%之后的 [1]副词告诉Printf函数再次使用第一个操作数。第二,%后的 # 副词告诉Printf在用%o、%x或%X输出时生成0、0x或0X前缀
o := 0666
fmt.Printf("%d %[1]o %#[1]o\n", o) // "438 666 0666"
x := int64(0xdeadbeef)
fmt.Printf("%d %[1]x %#[1]x %#[1]X\n", x)
// Output:
// 3735928559 deadbeef 0xdeadbeef 0XDEADBEEF
ascii := 'a'
unicode := '国'
newline := '\n'
fmt.Printf("%d %[1]c %[1]q\n", ascii) // "97 a 'a'"
fmt.Printf("%d %[1]c %[1]q\n", unicode) // "22269 国 '国'"
fmt.Printf("%d %[1]q\n", newline) // "10 '\n'"

3.2浮点数

划重点

  • float32
    float64
  • 常量math.MaxFloat32表示float32能表示的最大数值,大约是 3.4e38
  • math.MaxFloat64常量大约是1.8e308
  • 最小值近似为1.4e-45和4.9e-324
  • 因为
    float32
    的有效bit位只有23个,其它的bit位用于指数和符号;当整数大于23bit能表达的范围时,
    float32
    的表示将出现误差,建议使用
    float64
  • 小数点前面或后面的数字都可能被省略(例如
    .707
    1.
    )。很小或很大的数最好用科学计数法书写,通过
    e
    E
    来指定指数部分
  • +Inf -Inf NaN
  • 在浮点数中,NaN、正无穷大和负无穷大都不是唯一的,每个都有非常多种的bit模式表示,浮点数的相等比较是危险的,需要特别小心处理精度问题
nan := math.NaN()
fmt.Println(nan == nan, nan < nan, nan > nan) // "false false >false"

常用库及方法

  • math
    math.IsNaN
    math.NaN
    math.Pi
    math.Sin
    math.Cos
    math.Hypot(x, y)

3.3复数

划重点

  • complex64
    complex128
var x complex128 = complex(1, 2) // 1+2i
var y complex128 = complex(3, 4) // 3+4i
fmt.Println(x*y) // "(-5+10i)"
fmt.Println(real(x*y)) // "-5"
fmt.Println(imag(x*y)) // "10"
  • 复数也可以用
    ==
    !=
    进行相等比较

常用库及方法

  • image
    image.NewRGBA
    image.Rect
    img.Set
    ``
  • image/color
    color.Color
    color.Gray
    color.Black
  • image/png
    png.Encode
  • math/cmplx
    cmplx.Sqrt(-1)
    cmplx.Abs()
    ``

3.4布尔值

划重点

  • 布尔类型的值只有两种:
    true
    false
  • 布尔值可以和
    &&(AND)
    ||(OR)
    操作符结合,
    &&
    的优先级比
    ||
    高,下面的形式不需要小括号
if 'a' <= c && c <= 'z' ||
'A' <= c && c <= 'Z' ||
'0' <= c && c <= '9' {
// ...ASCII letter or digit...
}
  • 布尔值并不会隐式转换为数字值0或1,反之亦然

3.5字符串

划重点

  • 一个字符串是一个不可改变的字节序列。
  • 文本字符串通常被解释为采用UTF8编码的Unicode码点(rune)序列。
  • 内置的len函数可以返回一个字符串中的字节数目(不是rune字符数目)。
  • 索引操作
    s[i]
    返回第
    i
    个字节的字节值,
    i
    必须满足
    0 ≤ i< len(s)
    条件约束。
  • 如果试图访问超出字符串索引范围的字节将会导致panic异常。
  • i
    个字节并不一定是字符串的第
    i
    个字符,因为对于非ASCII字符的UTF8编码会要两个或多个字节。
  • +
    操作符将两个字符串链接构造一个新字符串。
  • 字符串可以用
    ==
    <
    进行比较;比较通过逐个字节比较完成的,因此比较的结果是字符串自然编码的顺序。
  • 字符串的值是不可变的:一个字符串包含的字节序列永远不会被改变,当然我们也可以给一个字符串变量分配一个新字符串值。
  • 因为字符串是不可修改的,因此尝试修改字符串内部数据的操作也是被禁止的。
s[0] = 'L' // compile error: cannot assign to s[0]
  • 不变性意味如果两个字符串共享相同的底层数据的话也是安全的,这使得复制任何长度的字符串代价是低廉的。同样,一个字符串s和对应的子字符串切片s[7:]的操作也可以安全地共享相同的内存,因此字符串切片操作代价也是低廉的。在这两种情况下都没有必要分配新的内存。下图演示一个字符串和两个字串共享相同的底层数据。
  • Go语言源文件总是用UTF8编码,Go语言的文本字符串也以UTF8编码的方式处理。

3.5.1字符串面值

划重点

  • 转义字符
\a 响铃
\b 退格
\f 换页
\n 换行
\r 回车
\t 制表符
\v 垂直制表符
\' 单引号 (只用在 '\'' 形式的rune符号面值中)
\" 双引号 (只用在 "..." 形式的字符串面值中)
\\ 反斜杠
  • 十六进制的转义形式是\xhh;一个八进制转义形式是\ooo
  • 一个原生的字符串面值形式是 …,使用反引号代替双引号。在原生的字符串面值中,没有转义操作;全部的内容都是字面的意思,包含退格和换行,因此一个程序中的原生字符串面值可能跨越多行(译注:在原生字符串面值内部是无法直接写字符的,可以用八进制或十六进制转义或
    +"```"
    链接字符串常量完成)
  • 原生字符串面值用于编写正则表达式(正则表达式会包含很多反斜杠)\HTML模板、JSON面值、命令行提示信息以及那些需要扩展到多行的场景
const GoUsage = `Go is a tool for managing Go source code.
Usage:
go command [arguments]
...`

3.5.2 Unicode

划重点

  • Unicode,码点对应Go语言中的
    rune
    整数类型(译注:
    rune
    int32
    等价类型)

3.5.3 UTF-8

划重点

  • UTF8编码由Go语言之父Ken Thompson和Rob Pike共同发明的,现在已经是Unicode的标准;
  • UTF8编码使用1到4个字节来表示每个Unicode码点,ASCII部分字符只使用1个字节,常用字符部分使用2或3个字节表示。如果第一个字节的高端bit是110,则说明需要2个字节;后续的每个高端bit都以10开头。
0xxxxxxx runes 0-127 (ASCII)
110xxxxx 10xxxxxx 128-2047 (values <128 unused)
1110xxxx 10xxxxxx 10xxxxxx 2048-65535 (values <2048 unused)
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 65536-0x10ffff (other values >unused)
  • Go语言字符串面值中Unicode码点输入特殊的字符。有两种形式:
    \uhhhh
    对应16bit的码点值,
    \Uhhhhhhhh
    对应32bit的码点值,其中
    h
    是一个十六进制数字,32bit的形式很少用。下面字符串面值表示的值相同:
"世界"
"\xe4\xb8\x96\xe7\x95\x8c"
"\u4e16\u754c"
"\U00004e16\U0000754c"

对于字符同样适用,下面的字符是等价的:

'世' '\u4e16' '\U00004e16'
  • Go语言的range循环在处理字符串的时候,会自动隐式解码UTF8字符串
  • UTF8
    utf8.DecodeRuneInString
    解码或
    range
    中隐式解码,遇到错误的UTF8编码,将生成一个特别的
    Unicode
    字符
    '\uFFFD'
    ,在印刷中会显示成"�"。
  • string
    []rune
    得到解码的Unicode字符序列;
s := "プログラム"
r := []rune(s)
fmt.Printf("%x\n", r) // "[30d7 30ed 30b0 30e9 30e0]"
  • []rune
    类型的Unicode字符
    slice
    或数组转为
    string
    ,则为
    UTF-8
    编码;
fmt.Println(string(r)) // "プログラム"
  • 整数转为字符串是生成以只包含对应Unicode码点字符的UTF8字符;
fmt.Println(string(65)) // "A", not "65"
fmt.Println(string(0x4eac)) // "京"
  • 对应码点的字符是无效的,则用’\uFFFD’无效字符作为替换;
fmt.Println(string(1234567)) // "�"

常用库及方法

  • unicode/utf8
    utf8.RuneCountInString(s)
    utf8.DecodeRuneInString
    utf8.EncodeRune()
    utf8.DecodeRune()

3.5.4字符串和Byte切片

划重点

  • 一个字符串是包含的只读字节数组,一旦创建,是不可变的。相比之下,一个字节slice的元素则可以自由地修改。两者之间的转换。
s := "abc"
b := []byte(s)
s2 := string(b)

常用库及方法
++四个重要的字符串处理包++

  • bytes
    主要针对的类型
    []byte
    ,和字符串结构类型相同,因为字符串是只读的,因此逐步构建字符串会导致很多分配和复制。所以
    bytes.Buffer
    更有优势。
    bytes.Contains
  • bytes.Count
  • bytes.Fields
  • bytes.HasPrefix
  • bytes.Index
  • bytes.Join
  • bytes.Buffer
  • bytes.Buffer.WriteByte
  • bytes.Buffer.WriteString
  • bytes.Buffer.WriteRune
    //对于UTF8编码
  • bytes.Buffer.String
  • strings
    包含查询、替换、比较、截断、拆分和合并。
      strings.Contains
    • strings.Count
    • strings.Fields
    • strings.HasPrefix
    • strings.Index
    • strings.Join
    • strings.LastIndex
  • strconv
    提供布尔型、整型数、浮点数和对应字符串的相互转换,还提供了双引号转义相关的转换
  • unicode
    提供
    IsDigit
    IsLetter
    IsUpper
    IsLower
    等类似功能,它们用于给字符分类。
    ToUpper
    ToLower
  • path
    path/filepath
    包提供了关于文件路径名更一般的函数操作。POSIX系统使用
    /foo/bar
    ,而Microsoft Windows使用
    c:\foo\bar
  • 3.5.5 字符串和数字的转换

    划重点

    • 整数->字符串 1.
      fmt.Sprintf
      2.
      strconv.Itoa(“整数到ASCII”)
    • 字符串->整数 1.
      strconv.Atoi
      3.
      strconv.ParseInt
    • fmt.Scanf
      来解析输入的字符串和数字

    常用库及方法

    • strconv
      strconv.Itoa
      strconv.FormatInt()
      strconv.Atoi
      strconv.ParseInt
    • fmt
      fmt.Scanf

    3.6常量

    划重点

    • 常量表达式的值在编译期计算,而不是在运行期。基础类型:boolean、string或数字。
    • 常量间的所有算术运算、逻辑运算和比较运算、类型转换的结果也是常量,以及下面的方法
      len、cap、real、imag、complex和unsafe.Sizeof
    • 批量声明的常量,除第一个外其他可以省略,省略的用上一个代替。

    常用库及方法

    3.6.1iota 常量生成器

    划重点

    • 第一个
      iota
      将会被置为0,然后在每一个有常量声明的行加一。
    • 类似于枚举
    type Weekday int
    
    const (
    Sunday Weekday = iota
    Monday
    Tuesday
    Wednesday
    Thursday
    Friday
    Saturday
    )
    const (
    _ = 1 << (10 * iota)
    KiB // 1024
    MiB // 1048576
    GiB // 1073741824
    TiB // 1099511627776 (exceeds 1 << 32)
    PiB // 1125899906842624
    EiB // 1152921504606846976
    ZiB // 1180591620717411303424 (exceeds 1 << 64)
    YiB // 1208925819614629174706176
    )

    常用库及方法

    3.6.2无类型常量

    划重点

    • 6种无类型常量:无类型的布尔型、无类型的整数、无类型的字符、无类型的浮点数、无类型的复数、无类型的字符串。
    • 延迟明确常量的具体类型,这样的好处是可以:1)保证精度;2)不需要显示的类型转换。
    var x float32 = math.Pi
    var y float64 = math.Pi
    var z complex128 = math.Pi
    • 对于常量面值,不同的写法可能会对应不同的类型。
    0 无类型的整数
    0.0 无类型的浮点数
    0i 无类型的复数
    '\u0000' 无类型的字符

    常用库及方法

    • 点赞
    • 收藏
    • 分享
    • 文章举报
    rabbit0206 发布了13 篇原创文章 · 获赞 3 · 访问量 134 私信 关注
    内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
    标签: 
    相关文章推荐