Golang对值之间有比较严格的限制,只有两个类型相同的值才可以比较,
格式化输出时可以使用%t表示你要输出的值是布尔类型
对于布尔值而言好的命名能很好提高代码的可读性。例如以is或者Is开头的isSorted、isFinished、isVisible。
数字类型
Go语言没有float类型只float32和float64,没有double类型。
float32精确到瞎弄书店后7位,float64精确到后15位,由于精确度的原因在使用==或!=时要小心!(正式使用前测试精确度较高的运算)
应该尽可能使用float64, 因为 math包中所有有关数学的函数都要求接受这个类型。
可以通过加前缀0来表示8进制数,通过加0x表示16进制数,用e来表示10的连乘。(1e3=1000)。
你可以使用a:=uint64(0)来同时完成类型的转换和赋值。
Go不允许不同类型之间的混合使用,但是对于常量的类型限制非常少,因此运行常量之间的混合使用。
以下程序无法通过编译:
package main
func main(){
var a int
var b int32
a=15
b=a+a//编译错误
b=b+5//因为5是常量所以编译成功
}
尝试编译,编译器显示
同时int16也不能隐式转换为int32。
所以需要显示转换解决问题
package main
import "fmt"
func main(){
var n int16=34
var m int32
//m=n
m=int32(n)
fmt.Printf("%d\n",m)
fmt.Printf("%d\n",n)
}
合并定义和声明在一行
合并后不显示转换
显示转换后成功编译
格式化说明符
在格式化字符串 %x %X表示格式化16进制数,%g用于格式化浮点数,%f输出浮点数,%e输出科学计数法,%0d用于输出定长的整数,%n.mg用于表示n宽度并精确到小数点后m位,除了使用g还可以使用e或者f,例如%5.2e来输出3.4的结果为3.40e+00 n
不够长就前补0
数字值转换
下面这个例子展示如何安全地从 int 型转换为 int8:?
func Uint8FromInt(n int) (uint8, error) {
if 0 <= n && n <= math.MaxUint8 { // conversion is safe
return uint8(n), nil
}
return 0, fmt.Errorf("%d is out of the uint8 range", n)
}
或者安全地从 float64 转换为 int:
func IntFromFloat64(x float64) int {
if math.MinInt32 <= x && x <= math.MaxInt32 { // x lies in the integer range
whole, fraction := math.Modf(x)
if fraction >= 0.5 {
whole++
}
return int(whole)
}
panic(fmt.Sprintf("%g is out of the int32 range", x))
}
实际存的数字超出你要转换到的类型的取值范围的话,则会引发 panic。
学习代码
package main
import (
"fmt"
"io"
"math/rand"
"strconv"
"strings"
"time"
"unicode/utf8"
)
/*
整型和浮点型数字,int\uint32 位os,32 位(4 个字节),64os,64 位(8 个字节)。
Go 语言中没有 float 类型。(Go 语言中只有 float32 和 float64)没有 double 类型。
?怎么表示
整数:
int8(-128 -> 127)
int16(-32768 -> 32767)
int32(-2,147,483,648 -> 2,147,483,647)
int64(-9,223,372,036,854,775,808 -> 9,223,372,036,854,775,807)
无符号整数:
uint8(0 -> 255)
uint16(0 -> 65,535)
uint32(0 -> 4,294,967,295)
uint64(0 -> 18,446,744,073,709,551,615)
浮点型(IEEE-754 标准):
float32(+- 1e-45 -> +- 3.4 * 1e38)
float64(+- 5 1e-324 -> 107 1e308)
你应该尽可能地使用 float64,因为 math 包中所有有关数学运算的函数都会要求接收这个类型。
!Go 中不允许不同类型之间的混合使用,但是对于常量的类型限制非常少
*/
/*
复数
complex64 (32 位实数和虚数)
complex128 (64 位实数和虚数)
在使用格式化说明符时,可以使用 %v 来表示复数,但当你希望只表示其中的一个部分的时候需要使用 %f
*/
/*
位运算
&同1为1
|有1为1
按位异或 ^ 不同为1
位清除 &^:将指定位置上的值设置为 0。
-01 ^ 10 = -11
bitP >> n。
bitP 的位向右移动 n 位,左侧空白部分使用 0 填充
负数变补码 负号不取反,其他取反+1 再^1 之后结果取反+1
位左移常见实现存储单位的用例
使用位左移与 iota 计数配合可优雅地实现存储单位的常量枚举:
*/
/*
随机数
*/
/*
运算符优先级
优先级 运算符
7 ^ !
6 * / % << >> & &^
5 + - | ^
4 == != < <= >= >
3 <-
2 &&
1 ||
*/
/*
字符类型
var ch byte = 65 或 var ch byte = '\x41'
(\x 总是紧跟着长度为 2 的 16 进制数)
另外一种可能的写法是 \ 后面紧跟着长度为 3 的八进制数,例如:\377。
不过 Go 同样支持 Unicode(UTF-8)
rune 也是 Go 当中的一个类型,并且是 int32 的别名
因为 Unicode 至少占用 2 个字节,所以我们使用 int16 或者 int 类型来表示。如果需要使用到 4 字节,则会加上 \U 前缀;前缀 \u 则总是紧跟着长度为 4 的 16 进制数,前缀 \U 紧跟着长度为 8 的 16 进制数。
前缀 \u 则总是紧跟着长度为 4 的 16 进制数,前缀 \U 紧跟着长度为 8 的 16 进制数。
unicode 包含了一些针对测试字符的非常有用的函数(其中 ch 代表字符):
判断是否为字母:unicode.IsLetter(ch)
判断是否为数字:unicode.IsDigit(ch)
判断是否为空白符号:unicode.IsSpace(ch)
*/
/*
字符串
`This is a raw string \n` 中的 `\n\` 会被原样输出。
和 C/C++ 不一样,Go 中的字符串是根据长度限定,而非特殊字符 \0
string 类型的零值为长度为零的字符串,即空字符串 ""
注意事项 获取字符串中某个字节的地址的行为是非法的,例如:&str[i]
在循环中使用加号 + 拼接字符串并不是最高效的做法,更好的办法是使用函数 strings.Join()(第 4.7.10 节),有没有更好地办法了?有!使用字节缓冲(bytes.Buffer)拼接更加给力(第 7.2.6 节)!
len() 函数:这个内建函数用来获取字符串的ASCII字符个数或字节长度。由于Go语言的字符串都以UTF-8格式保存,每个中文字符可能占用3个字节,因此使用len()获得的是字符串的字节长度,而不是字符数量
utf8.RuneCountInString() 函数:这个函数由UTF-8包提供,用来统计Unicode字符数量。它会正确地计算字符串中的Unicode字符数,无论每个字符占用多少字节
str1 只包含ASCII字符,所以len(str1)和utf8.RuneCountInString(str1)的值是相同的,都是字符串的字符数和字节数。
str2 包含了一个非ASCII字符(日文字符“こん”),这个字符在UTF-8编码中占用3个字节。因此,len(str2)计算的是整个字符串的字节长度,而utf8.RuneCountInString(str2)计算的是字符串中的Unicode字符数,包括多字节的字符。
*/
type ByteSize float64
const (
Iota = iota // 通过赋值给空白标识符来忽略值
KB ByteSize = 1 << (10 * iota)
MB
GB
TB
PB
EB
ZB
YB
)
func main() {
var a int
var b int32
a = 15
// b = a + a // 编译错误
b = int32(a + a) //编译成功
b = b + 5 // 因为 5 是常量,所以可以通过编译
fmt.Printf("b value is %v \n", b)
//复数
var c1 complex64 = 5 + 10i
fmt.Printf("The value c1 is: %v \n", c1)
c := complex(11, 22)
fmt.Printf("The value c is: %v \n", c)
fmt.Printf("The realc is: %v imag c is %v\n", real(c), imag(c))
//位运算
fmt.Printf("Signed: %d ^ %d = %d\n", 1, -10, 1^-10)
fmt.Printf("KB %v\n a %v\n", KB, Iota)
//随机数
for i := 0; i < 10; i++ {
r := rand.Int()
fmt.Printf("%d \n", r)
}
for i := 0; i < 10; i++ {
r := rand.Intn(10)
fmt.Printf("%d \n", r)
}
//设定随机数种子
timens := int64(time.Now().Nanosecond())
rand.Seed(timens)
for i := 0; i < 10; i++ {
fmt.Printf("%2.2f \n", 100*rand.Float32())
}
//字符
var ch int = '\u0041'
var ch2 int = '\u03B2'
var ch3 int = '\U00101234'
fmt.Printf("%d - %d - %d\n", ch, ch2, ch3) // integer
fmt.Printf("%c - %c - %c\n", ch, ch2, ch3) // character
fmt.Printf("%X - %X - %X\n", ch, ch2, ch3) // UTF-8 bytes
fmt.Printf("%U - %U - %U", ch, ch2, ch3) // UTF-8 code point
//字符串
fmt.Printf("`aa\\n`")
// 1.1count number of characters: 要注意len统计的是字节,考虑到不同编码字节数的不同,utf8.RuneCountInString能考虑的是ubicode字符数量
str1 := "asSASA ddd dsjkdsjs dk"
fmt.Printf("The number of bytes in string str1 is %d\n", len(str1))
fmt.Printf("The number of characters in string str1 is %d\n", utf8.RuneCountInString(str1))
str2 := "asSASA ddd dsjkdsjsこん dk"
fmt.Printf("The number of bytes in string str2 is %d\n", len(str2))
fmt.Printf("The number of characters in string str2 is %d\n", utf8.RuneCountInString(str2))
//1.2前缀
err := strings.HasPrefix(str1, "as")
print(err, "\n")
print(strings.Count(str1, "SA"), "\n")
err = strings.HasSuffix(str2, "dkk")
print(err, "\n")
err = strings.Contains(str1, "ddd ")
print(err, "\n")
//1.3判断子字符串在父字符串的位置 index
//染回6
print(strings.Index(str1, " ddd"), "\n")
//不存在-1返回
print(strings.Index(str1, " dddl"), "\n")
print(strings.Index(str1, "d"), "\n")
//1.4逆向索引 下标20而不是7
print(strings.LastIndex(str1, "d"), "\n")
//1.5如果 ch 是非 ASCII 编码的字符,建议使用以下函数来对字符进行定位:
r := 'ん'
print(strings.IndexRune(str2, r), "\n")
print(strings.Index(str2, string(r)), "\n")
//1.6替换
print(strings.Replace(str1, "d", "lin", 2), "\n")
//1.7重复字符串
print(strings.Repeat(str1, 2), "\n")
//修改字符串大小写
print(strings.ToLower(str1), "\n")
//修剪字符串
print(strings.TrimSpace("aaad a "), "kk \n")
//将开头和结尾在字符集里面的字符去掉
print(strings.Trim("akkbhuhgkkuk", "akbu"), "\n")
//分割字符串
fields := strings.Fields(str1)
for _, v := range fields {
print(v, ":")
}
print("\n")
//自定义分割符
fields = strings.Split("aa,b,121,1", ",")
for _, v := range fields {
print(v, ":")
}
//拼接 slice 到字符串
print(strings.Join(fields, "--"), "\n")
//从字符串中读取内容
str1Reader := strings.NewReader("hello")
bytes, _ := io.ReadAll(str1Reader)
print(string(bytes))
//Read() 从 [] byte 中读取内容。
//ReadByte() 和 ReadRune() 从字符串中读取下一个 byte 或者 rune。
//字符串与其它类型的转换
var orig string = "666"
var an int
var newS string
fmt.Printf("The size of ints is: %d\n", strconv.IntSize)
an, _ = strconv.Atoi(orig)
fmt.Printf("The integer is: %d\n", an)
an = an + 5
newS = strconv.Itoa(an)
fmt.Printf("The new string is: %s\n", newS)
}