前面四篇主题,分享了 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)
}
由于字数限制,本文就分享到这里。
如果觉得有价值,点赞支持
@李南江
由于部分好友可能等不及更新,建议先看电子书。