Java程序员的Go入门笔记
系列文章目录和关于我0.背景
3年java开发背景(因此这篇文章的特点是:比较适合java程序员doge),业余时间有了解过一些go,如今主要技术栈是go,此篇主要结合go语言圣经和团队内go项目,总结一些基础知识。
另外文章中没有对if,switch ,for进行说明,看多了文中的例子,自然就会这部分了
1.程序结构
1.1.声明、赋值和类型
Go语言主要有四种类型的声明语句:var、const、type和func,分别对应变量、常量、类型和函数实体对象的声明
以下是一个 Go 语言程序结构的代码示例:
// 结构体声明
type MyStruct struct {
name string
age int8
sex bool
userType UserType
sub *MyStruct
keys []string
featuremapany
}
// 类型
type UserType int64
// 常量声明
const (
SUPER UserType = 1
)
func main() {
// 常量声明
const sexBool bool = false
// 变量
var userName string
// 变量赋值
userName = "username"
//简短变量声明并赋值
userAge := 1
// map类型
userFeature := make(mapany)
// map赋值
userFeature["key"] = "value"
// 数组类型
var keys []string = make([]string, 20)
//数组类型赋值
keys = "!"
// 结构体
var subStruct = MyStruct{age: 1, userType: 1, sex: false, name: "1"}
myStruct := MyStruct{age: int8(userAge), userType: SUPER, sex: sexBool,
name: userName, feature: userFeature, sub: &subStruct, keys: keys}
}1.2.包和文件
包的概念和java中的包类似,不同的是导入包路径使用的是“/”进行分割
package main
import (
"errors"
"fmt"
)
import "code.byted.org/life_service/chenxinglandingdemo/compare" // 导入自定义的包该包中有一个文件int_comparator.go,定义了一个Compare函数
type IntPriority interface {
GetPriority() int
}
func Compare(first IntPriority, second IntPriority) (int, error) {
if first == nil || second == nil {
return 0, errors.New("null input")
}
firstPriority := first.GetPriority()
secondPriority := second.GetPriority()
if firstPriority == secondPriority {
return 0, nil
}
if firstPriority > secondPriority {
return 1, nil
}
return -1, nil
}引入包后的使用例子
compare.Compare(&myStruct, &subStruct)其中大写开头的方法才被视为是public的,这点一开始让我觉得有点草率,但是似乎确实比java的private,protected,public用起来更爽一点
使用init方法可以对包文件的初始化,有点类似java类中的static静态代码块,但是无论该文件是否被使用,都会执行init,不像java只有使用到这个类执行类的初始化后才会执行static
package compare
import "fmt"
func init() {
fmt.Println("init_method_learn.go")
}init方法的执行是依赖文件名称顺序的,因此如果A文件使用B文件中的方法是,也许B文件还没有调用init
2.基本数据类型
2.1 整形
Go语言同时提供了有符号和无符号类型的整数运算。这里有int8、int16、int32和int64四种截然不同大小的有符号整数类型,分别对应8、16、32、64bit大小的有符号整数,与此对应的是uint8、uint16、uint32和uint64四种无符号整数类型。
这里需要注意的是,int 和 uint 类型的大小取决于操作系统的位数。在32位操作系统中,int 和 uint 类型的大小通常为4字节(32位);在64位操作系统中,它们的大小通常为8字节(64位)。我看我们系统中一般是没有直接使用int和unit的。
2.2 浮点数
Go语言提供了两种精度的浮点数,float32和float64。它们的算术规范由IEEE754浮点数国际标准定义,该浮点数规范被所有现代的CPU支持。
和其他语言一样,float32和float64都有一定精度误差
var f float32 = 16777216
// true
fmt.Println(f+1 == f)
var f64 float64 = 16777216
// true
fmt.Println(f64+0.000000000000001 == f64)在 IEEE 754 标准中,float32 类型的浮点数使用 32 位来存储,其中包括 1 位符号位(S)、8 位指数位(E)和 23 位尾数位(M)。对于数字 16777216,将其转换为二进制表示为 1000000000000000000000000。将其转换为 IEEE 754 格式的 float32 类型,具体步骤如下:
[*]符号位 S:16777216 是正数,所以符号位 S 为 0。
[*]指数位 E:将二进制数 1000000000000000000000000 右移 23 位,得到指数为 24。由于指数位的偏移量为 127,所以实际的指数值为 24 - 127 = -103。
[*]尾数位 M:取二进制数 1000000000000000000000000 的后 23 位,即 00000000000000000000000,省略掉开头的 1。
因此,16777216 在 IEEE 754 存储中的表示为:0 10000001 00000000000000000000000。
对于数字 16777217,按照同样的步骤转换为 IEEE 754 格式的 float32 类型:
[*]符号位 S:16777217 是正数,所以符号位 S 为 0。
[*]指数位 E:将二进制数 1000000000000000000000001 右移 23 位,得到指数为 24。由于指数位的偏移量为 127,所以实际的指数值为 24 - 127 = -103。
[*]尾数位 M:取二进制数 1000000000000000000000001 的后 23 位,即 000000000000000000000001,省略掉开头的 1。
所以,16777217 在 IEEE 754 存储中的表示也是:0 10000001 00000000000000000000000。
这就是为什么 16777216 和 16777217 在 IEEE 754 存储中看起来是一样的原因,它们的尾数位相同,而指数位也相同,只是在转换为十进制时,由于精度限制,会出现舍入误差,导致结果略有不同。
和java一样go也提供big来解决这个问题
// 使用 math/big 包进行高精度计算
a := new(big.Float).SetPrec(128).SetFloat64(0.000000000000001)
b := new(big.Float).SetPrec(128).SetFloat64(16777216)
c := new(big.Float).Add(a, b)
// 输出1,表示c大于b,符合预期
fmt.Println(c.Cmp(b))2.3 bool 布尔
类似于java中的boolean,在 Go 语言中,布尔型数据只有true和false两个值,没有像 Java 中那样的Boolean类型。
2.4 字符串
func main() {
str := "testStr测试字符串"
// 输出22 ===>7+15(汉子3个字符)
fmt.Println(len(str))
// 输出116 utf8编码
var u uint8 = str
fmt.Println(u)
// 输出116 utf8编码
fmt.Println(str)
// testStr
fmt.Println(str)
// testStr
fmt.Println(str[:7])
//测试字符串
fmt.Println(str)
// 测试字符串
fmt.Println(str)
// 字符串循环
for i := range str {
fmt.Println(string(str))
}
}如上是字符串常用的一些操作,go中的字符串也是不可变的
让我比较迷惑的是str这种字符串的操作似乎是深拷贝,但是有一些文档也说是浅拷贝
3.复合数据类型
3.1 数组
// 声明,然后赋值
ints := int{}
ints = 1
// 声明并赋值,没有赋值的index使用初值0
var ints2 int = int{1, 2, 3, 4, 5}
fmt.Println(ints2)
fmt.Println(len(ints2))
// 根据元素的个数来自动设置长度
ints3 := [...]int{1, 2, 3, 4, 5}
fmt.Println(len(ints3))
ints4 := [...]int{99: -1}
// 长度为100 = 99+1
fmt.Println(len(ints4))
ints5 := int{1, 2, 3, 4, 5}
// true
fmt.Println(ints3 == ints5)其中我觉得比较有意思的是
[*]数组的比较:
如果一个数组的元素类型是可以相互比较的,那么数组类型也是可以相互比较的,这时候我们可以直接通过==比较运算符来比较两个数组,只有当两个数组的所有元素都是相等的时候数组才是相等的。不相等比较运算符!=遵循同样的规则。
[*]数组类型
int和int是不同的类型
因此两个不太类型的数组是不可以比较的
以及也不能把int类型的变量使用=赋值一个int 类型的变量
<ul>数组作为参数<ul>
数组作为参数是值传递,这意味着下面clearArray1方法是无法清空数组内容的,使用指针的clearArray2是可以清空的(这也启发我们,比较占用内存的变量应该使用指针,因为指针作为参数值拷贝浪费的内存少,拷贝的是指针对象!)
[*]func clearArray1(array int) {
for i := range array {
array = 0
}
}
func clearArray(array *int) {
for i := range array {
array = 0
}
}
因为int和int是不太同的数组类型,因此上面两个函数,都只能穿入长度为5的数组,这一点让我觉得有点恶心
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页:
[1]