前面四篇主题,分享了 Go 语言的发展历史,现状,Go 语言与 C 语言对比,如何学习 Go 语言,Go 语言 IDE 安装方法,Go 语言基础知识,Go语言注释、Go语言编码风格、关键字、标识符、数据类型、变量、数据类型转换等知识点。

第五期,继续和大家分享 Go 语言基础知识点、Go 语言常量

数值类型和字符串类型之间转换

  • Go语言中不能通过 数据类型(变量)的格式将数值类型转换为字符串, 也不能通过 数据类型(变量)的格式将字符串转换为数值类型
    package main
    import "fmt"
    func main() {
        var num1 int32 = 65
        // 可以将整型强制转换, 但是会按照ASCII码表来转换
        // 但是不推荐这样使用
        var str1 string = string(num1)
        fmt.Println(str1)
​
        var num2 float32 = 3.14
        // 不能将其它基本类型强制转换为字符串类型
        var str2 string = string(num2)
        fmt.Println(str2)
​
        var str3 string = "97"
        // 不能强制转换, cannot convert str2 (type string) to type int
        var num3  int = int(str3)
        fmt.Println(num3)
    }
strconv..FormatXxx()
    package main
    import "fmt"
    func main() {
        var num1 int32 = 10
        // 第一个参数: 需要被转换的整型,必须是int64类型
        // 第二个参数: 转换为几进制,  必须在2到36之间
        // 将32位十进制整型变量10转换为字符串,并继续保留10进制格式
        str1 := strconv.FormatInt(int64(num1), 10)
        fmt.Println(str1) // 10
        // 将32位十进制整型变量10转换为字符串,并转换为2进制格式
        str2 := strconv.FormatInt(int64(num1), 2)
        fmt.Println(str2) // 1010
​
        var num5 float64 = 3.1234567890123456789
        // 第一个参数: 需要转换的实型, 必须是float64类型
        // 第二个参数: 转换为什么格式,f小数格式, e指数格式
        // 第三个参数: 转换之后保留多少位小数, 传入-1按照指定类型有效位保留
        // 第四个参数: 被转换数据的实际位数,float32就传32, float64就传64
        // 将float64位实型,按照小数格式并保留默认有效位转换为字符串
        str3 := strconv.FormatFloat(num5, 'f', -1, 64)
        fmt.Println(str3) // 3.1234567
        str4 := strconv.FormatFloat(num5, 'f', -1, 64)
        fmt.Println(str4) // 3.1234567890123457
        // 将float64位实型,按照小数格式并保留2位有效位转换为字符串
        str5 := strconv.FormatFloat(num5, 'f', 2, 64)
        fmt.Println(str5) // 3.12
        // 将float64位实型,按照指数格式并保留2位有效位转换为字符串
        str6 := strconv.FormatFloat(num5, 'e', 2, 64)
        fmt.Println(str6) // 3.12
​
        var num6 bool = true
        str7 := strconv.FormatBool(num6)
        fmt.Println(str7) // true
    }
strconv.ParseXxx()
    package main
    import "fmt"
    func main() {
        var str1 string = "125"
        // 第一个参数: 需要转换的数据
        // 第二个参数: 转换为几进制
        // 第三个参数: 转换为多少位整型
        // 注意点: ParseInt函数会返回两个值, 一个是转换后的结果, 一个是错误
        // 如果被转换的数据转换之后没有超出指定的范围或者不能被转换时,
        // 那么错误为nil, 否则错误不为nil
        // 将字符串"125"转换为10进制的int8
        num1, err := strconv.ParseInt(str1, 10, 8)
        if err != nil {
            fmt.Println(err)
        }
        fmt.Println(num1)
​
        var str2 string = "150"
        // 将字符串"150"转换为10进制的int8
        // 由于int8的取值范围是-128~127, 所以转换之后超出了指定的范围, error不为nil
        num2, err := strconv.ParseInt(str2, 10, 8)
        if err != nil {
            fmt.Println(err)
        }
        fmt.Println(num2)
​
        var str3 string = "3.1234567890123456789"
        // 第一个参数: 需要转换的数据
        // 第二个参数: 转换为多少位小数, 32 or 64
        // ParseFloat同样有两个返回值, 如果能够正常转换则错误为nil, 否则不为nil
        num3, err := strconv.ParseFloat(str3, 32)
        if err != nil {
            // 例如: 把字符串"3.14abc"转换为小数就会报错, 因为"3.14abc"不是一个小数
            fmt.Println(err)
        }
        fmt.Println(num3)
​
        var str4 string = "true"
        // 第一个参数: 需要转换的数据
        // ParseBool同样有两个返回值, 如果能够正常转换则错误为nil, 否则不为nil
        num4, _ := strconv.ParseBool(str4)
        fmt.Println(num4)
    }
  • 字符串类型转换为数值类型时,如果不能转换除了返回error以外,还会返回对应类型的默认值
    package main
    import "fmt"
    func main() {
        var str1 string = "abc"
        num1, _ := strconv.ParseInt(str1, 10, 32)
        fmt.Println(num1) // 0
​
        num2, _ := strconv.ParseFloat(str1, 32)
        fmt.Println(num2) // 0
​
        num3, _ := strconv.ParseBool(str1)
        fmt.Println(num3) // false
    }
  • 看完上面的代码有没有种想打人的感觉? 如果有那么请继续往下看
  • 字符串类型和整型快速转换
    package main
    import "fmt"
    func main() {
        var num1 int32 = 110
        // 快速将整型转换为字符串类型
        // 注意:Itoa方法只能接受int类型
        var str1 string = strconv.Itoa(int(num1))
        fmt.Println(str1)
​
        var str2 string = "666"
        // 快速将字符串类型转换为整型
        // 注意: Atoi方法返回两个值, 一个值是int,一个值是error
        // 如果字符串能被转换为int,那么error为nil, 否则不为nil
        num2, err := strconv.Atoi(str2)
        if err != nil{
            fmt.Println(err)
        }
        fmt.Println(num2)
    }
  • 数值类型转字符串类型其它方式
package main
import "fmt"
func main() {
 var num1 int32 = 110
 // Sprintf函数和Printf函数很像, 只不过不是输出而将格式化的字符串返回给我们
 var str1 string = fmt.Sprintf("%d", num1)
 fmt.Println(str1)
​
 var num2 float32 = 3.14
 var str2 string = fmt.Sprintf("%f", num2)
 fmt.Println(str2)
​
 var num3 bool = true
 var str3 string = fmt.Sprintf("%t", num3)
 fmt.Println(str3)
}

Go语言常量

整型常量实型常量字符常量字符串常量自定义常量const 数据类型 常量名称 = 值;
 #include <stdio.h>
 int main(int argc, const char * argv[])
  {
 const float PI = 998;
 PI = 110; // 报错
 printf("PI = %d\n", PI );
 return 0;
  }
const 常量名称 数据类型 = 值const 常量名称  = 值
package main
import "fmt"
func main() {
//const PI float32 = 3.14
//PI = 110 // 报错
//fmt.Println("PI = ", PI )
​
const PI = 3.14
PI = 110 // 报错
fmt.Println("PI = ", PI )
}
一次性定义多个常量
package main
import "fmt"
func main() {
// 多重赋值方式
const num1, num2 int = 100, 200
fmt.Println("num1 = ", num1)
fmt.Println("num2 = ", num2)
​
// 常量组方式
const (
 num3 = 100
 num4 = 200
)
fmt.Println("num3 = ", num3)
fmt.Println("num4 = ", num4)
​
// 常量组+多重赋值
const (
 num5, num6 = 100, 200
 num7 = 300
)
fmt.Println("num5 = ", num5)
fmt.Println("num6 = ", num6)
fmt.Println("num7 = ", num7)
}


  • Go语言自定义常量注意点
    • 定义的局部变量或者导入的包没有被使用, 那么编译器会报错,无法编译运行
    • 但是定义的常量没有被使用,编译器不会报错, 可以编译运行
package main
import "fmt"
func main() {
// 可以编译运行
const PI float32 = 3.14
}
    • 在常量组中, 如果上一行常量有初始值,但是下一行没有初始值, 那么下一行的值就是上一行的值
package main
import "fmt"
func main() {
const (
 num1 = 998
 num2 // 和上一行的值一样
 num3 = 666
 num4 // 和上一行的值一样
 num5 // 和上一行的值一样
)
fmt.Println("num1 = ", num1) // 998
fmt.Println("num2 = ", num2) // 998
fmt.Println("num3 = ", num3) // 666
fmt.Println("num4 = ", num4) // 666
fmt.Println("num5 = ", num5) // 666
​
const (
 num1, num2 = 100, 200
 num3, num4 // 和上一行的值一样, 注意变量个数必须也和上一行一样
)
fmt.Println("num1 = ", num1)
fmt.Println("num2 = ", num2)
fmt.Println("num3 = ", num3)
fmt.Println("num4 = ", num4)
}


  • 枚举常量
    • C语言中枚举类型的本质就是整型常量
    • Go语言中没有C语言中明确意义上的enum定义, 但是可以借助iota标识符来实现枚举类型


  • C语言枚举格式:
 enum 枚举名 {
    枚举元素1,
    枚举元素2,
    … …
 };
C语言枚举中,如果没有指定初始值,那么从0开始递增


#include <stdio.h>
int main(int argc, const char * argv[])
{
 enum Gender{
 male,
 female,
 yao,
    };
//    enum Gender g = male;
//    printf("%d\n", g); // 0
//    enum Gender g = female;
//    printf("%d\n", g); // 1
 enum Gender g = yao;
 printf("%d\n", g); // 2
 return 0;
}
    • C语言枚举中, 如果指定了初始值,那么从指定的数开始递增
#include <stdio.h>
int main(int argc, const char * argv[])
{
 enum Gender{
 male = 5,
 female,
 yao,
    };
//    enum Gender g = male;
//    printf("%d\n", g); // 5
//    enum Gender g = female;
//    printf("%d\n", g); // 6
 enum Gender g = yao;
 printf("%d\n", g); // 7
 return 0;
}


  • Go语言实现枚举格式
const(
  枚举元素1 = iota
  枚举元素2 = iota
  ... ...
)
利用iota标识符标识符实现从0开始递增的枚举

package main
import "fmt"
func main() {
 const (
  male = iota
  female = iota
  yao = iota
 )
 fmt.Println("male = ", male) // 0
 fmt.Println("male = ", female) // 1
 fmt.Println("male = ", yao) // 2
}
每一行递增1
 package main
 import "fmt"
 func main() {
 const (
  male = iota // 这里出现了iota
  female // 这里会自动递增
  yao
 )
 fmt.Println("male = ", male) // 0
 fmt.Println("male = ", female) // 1
 fmt.Println("male = ", yao) // 2
 }
    • 在同一个常量组中,如果iota被中断, 那么必须显示恢复
package main
import "fmt"
func main() {
 const (
  male = iota 
  female = 666 // 这里被中断, 如果没有显示恢复, 那么下面没有赋值的常量都和上一行一样
  yao
 )
 fmt.Println("male = ", male) // 0
 fmt.Println("male = ", female) // 666
 fmt.Println("male = ", yao) // 666
}
package main
import "fmt"
func main() {
 const (
  male = iota 
  female = 666 // 这里被中断
  yao = iota // 这里显示恢复, 会从当前常量组第一次出现iota的地方开始,每一行递增1, 当前是第3行,所以值就是2
 )
 fmt.Println("male = ", male) // 0
 fmt.Println("male = ", female) // 666
 fmt.Println("male = ", yao) // 2
}
    • iota也支持常量组+多重赋值, 在同一行的iota值相同
 package main
 import "fmt"
 func main() {
 const (
  a, b = iota, iota
  c, d = iota, iota
    )
 fmt.Println("a = ", a) // 0
 fmt.Println("b = ", b) // 0
 fmt.Println("c = ", c) // 1
 fmt.Println("d = ", d) // 1
  }
    • iota自增默认数据类型为int类型, 也可以显示指定类型
 package main
 import "fmt"
 func main() {
 const (
  male float32 = iota // 显示指定类型,后续自增都会按照指定类型自增
  female
  yao
  )
fmt.Printf("%f\n", male) // 0.0
fmt.Printf("%f\n", female) // 1.0
fmt.Printf("%f\n", yao) // 2.0
 fmt.Println("male = ", reflect.TypeOf(female)) // float32
  }
  • Go语言fmt包实现了类似C语言printf和scanf的格式化I/O, 格式化动作源自C语言但更简单 ##输出函数
  • func Printf(format string, a ...interface{}) (n int, err error)
    • 和C语言用法几乎一模一样, 只不过新增了一些格式化符号
package main
import "fmt"
func main() {
 name := "微信搜索:代码情缘"
 age := 33
 fmt.Printf("name = %s, age = %d\n", name, age) // name = lnj, age = 33
}
还可以
package main
import "fmt"
func main() {
 num := 15
 fmt.Printf("十进制 = %d\n", num)
 fmt.Printf("八进制 = %o\n", num)
 fmt.Printf("十六进制 = %x\n", num)
 fmt.Printf("二进制 = %b\n", num)
}
    • 除此之外,Go语言还增加了%T控制符, 用于输出值的类型
package main
import "fmt"
func main() {
type Person struct {
 name string
 age int
}
num1 := 10
num2 := 3.14
per := Person{"lnj", 33}
fmt.Printf("num1 = %T\n", num1) // int
fmt.Printf("num2 = %T\n", num2) // float64
fmt.Printf("per = %T\n", per) // main.Person
}
    • 除此之外,Go语言还增加了%v控制符,用于打印所有类型数据
      • Go语言中输出某一个值,很少使用%d%f等, 一般都使用%v即可
      • 输出复合类型时会自动生成对应格式后再输出


package main
import "fmt"
func main() {
type Person struct {
 name string
 age int
}
num1 := 10
num2 := 3.14
per := Person{"lnj", 33}
// 此时相当于把%v当做%d
fmt.Printf("num1 = %v\n", num1) // 10
// 此时相当于把%v当做%f
fmt.Printf("num2 = %v\n", num2) // 3.14
}
    • Go语言Printf函数其它特性,如宽度、标志、精度、长度、转移符号等,和C语言一样.



package main
import "fmt"
func main() {
num1 := 10
num2 := 3.14
fmt.Println(num1, num2) // 10 3.14
fmt.Println("num1 =", num1, "num2 =", num2) // num1 = 10 num2 = 3.14
​
type Person struct {
 name string
 age int
}
per := Person{"lnj", 33}
fmt.Println(per) // {lnj 33}
}


不会都不是


package main
import "fmt"
func main() {
num1 := 10
num2 := 3.14
fmt.Print(num1, num2) // 10 3.14
fmt.Print("num1 =", num1, "num2 =", num2) // num1 =10 num2 =3.14
​
type Person struct {
 name string
 age int
}
per := Person{"lnj", 33}
fmt.Print(per) // {lnj 33}
}


  • 以下三个函数和Printf/Println/Print函数一样, 只不过上面三个函数是输出到标准输出, 而下面三个函数可以通过w指定输出到什么地方
  • func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error)
  • func Fprintln(w io.Writer, a ...interface{}) (n int, err error)
  • func Fprint(w io.Writer, a ...interface{}) (n int, err error)
package main
import (
    "fmt"
    "net/http"
    "os"
)
func main() {
    // os.Stdout 写入到标准输出
    name := "lnj"
    age := 33
    // 第一个参数: 指定输出到什么地方
    // 第二个参数: 指定格式控制字符串
    // 第三个参数: 指定要输出的数据
    fmt.Fprintf(os.Stdout, "name = %s, age = %d\n", name, age)
​
    // http.ResponseWriter 写入到网络响应
    http.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {
        fmt.Fprintf(writer, "name = %s, age = %d\n", name, age)
    })
    http.ListenAndServe(":8888", nil)
}


以下三个函数和Printf/Println/Print函数一样, 只不过上面三个函数是输出到标准输出, 而下面三个函数不会输出,而是将字符串返回给我们

  • func Sprintf(format string, a ...interface{}) string
  • func Sprint(a ...interface{}) string
  • func Sprintln(a ...interface{}) string
package main
import (
    "fmt"
    "net/http"
    "os"
)
func main() {
    name := "lnj"
    age := 33
    // 按照指定的格式生成字符串
    str := fmt.Sprintf("name = %s, age = %d\n", name, age)
    // 输出生成的字符串
    fmt.Println(str)
}

由于字数限制,本文就分享到这里。

如果觉得有价值,点赞支持

@李南江

由于部分好友可能等不及更新,建议先看电子书。