目录
本文主要讲解Go中基础数据类型,字符串、整数、浮点数、布尔这几个类型,像slice、map、struct等类型会有单独文章讲解
本文概要
- 1、要转换思维,尽可能的不再定义弱类型,比如Go里的interface{}
- 2、务必要注意强类型里的默认值
一、基础类型对比
我们在很多文章中都能看到类似的说明,这里copy一份,仅供参考
| 语言\类型 | boolean | string | int | float | array |
|---|---|---|---|---|---|
| PHP | bool | string | int | float | [1,2,3]/["a"=>1] |
| Go | bool | string | int、int8、int16、int32、int64、uint、uint8、uint16、uint32、uint64 | float32、float64 | slice/map |
二、认知和使用差异点
对于强类型语言只有类型相同的值才能够比较
<?php $a = 1; $b = "1"; $c = true; var_dump($a == $b); var_dump($b == $c); var_dump($a == $c); // Output,当然php也支持强类型的判等比较 === bool(true) bool(true) bool(true)
package main
import "fmt"
func main() {
a := int32(1)
b := int64(2)
if a == b { // 这一行直接报错,根本无法编译过去
fmt.Println("相等")
}
}
变量必须声明并初始化
在PHP中可以随时声明一个变量并赋予任意类型的任意值,这在Go中是行不通的,在强类型语言中,必须要提前声明变量类型,当然可以显示的声明,也可以是推导式的声明,并且Go中的所有类型都是有默认值的
package main
import "fmt"
func main() {
var a string // 默认空字符串
var b int // 所有int都默认0
var c float64 // 所有float64都默认0
d := false // 推导出d是布尔值,bool值默认false
fmt.Println(a, b, c, d)
// b = "1" // 这种赋值会直接报错
}
// Output, 需注意string默认值为空字符串,所以未能有效输出展示
0 0 false
protobuf中也会利用默认值的特性,不传递变量是默认值的数据,减少传输数据量
如何做类型转换
(int)(string)
package main
import (
"fmt"
"strconv"
)
func main() {
a := "1"
b := 1.0
var c interface{}
c = "2"
d, _ := strconv.Atoi(a)
f, _ := strconv.Atoi(c.(string))
fmt.Println(int(b)) // int和float之间可以直接转换,但是要注意范围溢出的问题
fmt.Println(d, f) // 字符串转数字需要使用特定函数,还要注意错误
fmt.Printf("%d %.1f", bb, b) // 其他类型转字符串,使用格式化字符串函数,最简单直观
}
Go中使用类型转换最流行的一个库就是 spf13/cast 库了,强烈建议直接引用,不要自己造轮子,需要注意的是 cast 库避免了 panic,所以在很多转换过程中,对于失败的案例,返回值就变成了变量默认值,这个需要看下自己业务场景是否正常
Unicode字符处理
mb_
<?php $a = "我爱中国"; echo "字节长度:", strlen($a),"字符串长度:", mb_strlen($a); // output: 字节长度:12字符串长度:4
rune[]byte[]rune
package main
import "fmt"
func main() {
str := "我爱中国"
fmt.Println("len", len(str), len([]rune(str)))
fmt.Println(string([]rune(str)[1:])) // 如果这里不转为[]rune,则处理unicode字符时会出现乱码
}
// Output
len 12 4
爱中国
三、基础类型使用中的常见坑
1.json转换失败,引起异常
这里核心讲下类型引起的异常,其实强语言与js这种弱类型交互处理json坑真的很多
{"key":null}json.Unmarshaljson.Unmarshaljson.Marshal
json的处理值得写一篇单独文章来讲解,这里许个诺,稍后期待补充
2.float的精度问题
Golang中同样有浮点数精度问题的坑
package main
import (
"fmt"
"math/big"
)
func main() {
f := 0.6
ff := 0.7
fmt.Println(f + ff)
a, _ := new(big.Float).SetString("0.6")
b, _ := new(big.Float).SetString("0.7")
// 加法运算
cccc := new(big.Float).Add(a, b)
fmt.Println("Add:", cccc.String())
}
// Output
Add: 1.2999999999999998
Add: 1.3
可见对于高精度需求的计算时这还是有点问题的,Golang自带的math包可以有效的解决这个问题,另外推荐第三方库https://github.com/shopspring/decimal也能很好的解决这个问题,使用起来可能更方便一点~
您可能感兴趣的文章: