Go的问题
Go的问题
itoa
是个什么
就是一个常量计数器, 只能用于const
中. 我觉得没啥用, 一点通用性都没有, 作用也非常有限. 忘记它都可以,java
中有这样的东西吗? 好像是有的, 叫什么生成器., 但这个有些用, 也具有通用性.int
和uint
有什么用, 已经有int8
,int16
,int32
,int64
和uint
,uint8
,uint16
,uint32
,uint64
int
和uint
应该是在程序内部自己使用的, 如果要调用外部的接口, 也就是别人包里面的东西, 肯定只能用确定位数的数字, 否则大小有可能不匹配, 会吗.go
编译的时候应该也会把别人包里面的东西一起编译吧, 会吗? 那go
没哟编译好的库吗? 所有的东西都要自己编译吗?java
是怎么引入jar
包的呢?go
语言的包管理是真的乱, 下载的包的位置, 找包的路径,go get
这个东西又一直在变,go install
又是什么东西, 下载了包为什么还要自己编译, 真是吐了.java
如何使用jar
包呢.java
和go
对于编译成包, 和使用包都有些复杂, 复杂吗? 学习这些语言时, 好像都不关心这些东西? 真的不重要吗?- “如果是在函数外部定义, 那么将在当前包的所有文件中都可以访问”. 包是类或者类的集合, 包中还可以包含包, 包用于组织类或者结构.
go
语言中有声明和定义和区别吗?java
有吗?go
区分函数的声明和定义吗? 现在go
函数的定义不需要出现使用之前go
语言不存在未初始化的值, 无论是包级别的变量, 还是函数内部的, 都会被赋零值. 那怎么区分不存在和零值呢? 例如输入空字符串和不输入字符串- 短变量声明只能用于函数内部吗? 为什么不能用于包级别呢? 有没有什么区别?
- 当短变量声明对某个变量进行赋值时, 这个变量在函数内还是函数外, 会决定这个是赋值, 还是声明, 这可能会导致不熟悉
go
语言的人写出bug
.java
没有这种赋值和定义同时进行的操作, 只能同时定义,int a = 10, b = 20;
- 为什么
go
的可运行程序的第一个非注释行必须是package main
?go
语言中package
与文件路径无关, 那它有什么用呢? go
语言允许返回局部变量的地址, 且这个地址是有效的, 不会被覆盖, 这个跟c
语言不同,c
语言地址里面的值是会被修改, 导致不可用, 这个更像java
中的返回函数中new
的对象. 看来go
跟c
的实现存在明显区别java
没有自带的命令行参数解析库, 需要自己去下载jar
包, 这里可以借助maven
- 如果类型的大小为0, 例如
struct{}
和[0]int
, 可能会有相同的地址, 同时go
语言对于大小为0的结构的处理还存在问题, 那为什么不修呢 new
只是一个预定义的函数, 不是一个关键字, 我们因此可以将new
名字重新定义为别的类型. 这个该说是go
语言的有点呢, 还是确定呢? 我认为还是缺点更大一些, 反正都有别的关键字了, 多这一个也不多啊. 也可以认为new
并不重要, 毕竟可以通过返回内部变量的地址来达到同样的效果go
语言的每一行不是以分号分隔的, 有一种复杂的规则来认定一行, 值得吗, 为了省一个分号go
自己判断变量是在栈上分配空间还是在堆上分配空间, 不是靠new
来决定的, 真是增加了理解程序的难度, 和c
语言完全不同go
语言中++
和--
是语句, 不可以在++
和--
的同时再进行赋值, 而在java
中是允许的,go
中这种强制行为, 感觉不灵活, 应该还是缺点更多go
的元组赋值(多变量同时赋值), 比起java
多了一种选择go
中返回多个值的函数, 还能用说与返回值个数的变量接收, 导致和全部接收不同的结果. 简直离谱. 例如map
的取值操作go
语言只用常量的赋值才会发生隐式类型转换吗?java
只有数值类型的赋值和计算才会发生隐式转换, 什么是隐式转换呢?go
语言中type
的用法是type 类型名字 底层类型
, 与c
语言的顺序相反,type
就是为了给类型一个别名, 就是为了增加代码可读性吗, 还可以防止类型混用- 打印时的
%v
,%s
,%g
有什么区别, 为什么会有这么多种打印一个类型值的方式 float64(1.0)
和1.0
虽然底层类型时相同的, 但是一个是命名了, 一个是未命名. 未命名的可以用于赋值给 相同底层数据结构的变量(运算符都是支持的)- 直接命名基本数据类型, 还是得到运算操作, 只能说聊生于无吧
go
语言中一个目录下只能有一个包, 也就是说package xxx
,xxx
必须相同,xxx
还会作为别的包使用这个包时带的前缀, 同一个包中可以不带前缀. 感觉跟java
的包还是有些不同的go moudle
语言对于包导入, 不再依赖$GOPATH
, 那它从那里找包呢?go mod
文件定义了一个模块名, 导入包时, 以这个模块名开头的路径, 会把不带模块头的路径作为相对路径, 从go mod
文件所在文件夹, 开始找包. 感觉比java
指定类路径的方式复杂了go
包的初始化, 外部变量循环依赖怎么办, 内部包级变量循环依赖怎么办? 感觉比java
的复杂- 一个程序可能包含多个同名的声明, 只要它们在不同的词法域就没有关系. 这个跟
c
语言是一样的 go
语言中if
语句的判断条件中可以定义变量, 而且这个变量还可以在整个if
和else
语句体中使用, 是一个全新的写法, 之前没有任何一种编程语言使用过这种方式, 有增加了复杂度go
语言中包级别的变量按照依赖顺序进行解析和初始化, 局部变量只会按照执行顺序初始化go
语言的main
函数的参数是空, 更java
和c
语言不一样, 如果要使用命令行参数, 就得使用go
自带的一个库go
语句只有局部变量会检查是否被使用吗, 包级变量不会吗?go
语言把数据类型分成了四类, 基础数据类型, 复合类型, 引用类型和接口类型. 字符串为什么被归为基础数据类型呢, 它不是一个数组吗. 数组为什么是复合类型, 不是引用类型?, 指针不是一个值吗, 为什么不是基础类型呢, 接口类型不是引用类型吗?go
的数据分类的根据是什么呢, 真是看不懂go
语言中int
和uint
的大小, 不仅和编译器, 还和平台有关系, 我们根本不知道它的大小, 我们该怎么使用它呢. 这是不是说明go
编译的程序, 无法在32位和64位上同时运行, 需要同时编译,uintptr
的大小也跟平台有关, 是不是用到了, 就得在特定的机器上编译呢? 那有点麻烦, 但是还好, 不用修改源码, 重新编译就行- 为什么
rune
用int32
作为底层,byte
用int8
作为底层, 一个用有符号数, 一个用符号数, 明明只是一个编码, 不关注数据的正负 go
语言有<<
和>>
, 用的是逻辑位移还是算术位移呢,c
的呢, 反正java
有<<<
和>>>
来做区分.go
语言中, 在x<<n
中,n
必须是无符号数, 为什么呢, 正的有符号数不行吗?go
语言的>>
是算术左移, 但可以通过类型转换来实现首位的填充值,java
只有有符号数所以用了两种位移来实现go
语言的&^
是啥运算符, 叫做AND NOT
, 位清空, 有什么用呢, 别的语言都没有? 通过与, 或, 非, 应该也可以实现吧go
语言中%
只能用于整数运算,c
语言和java
语言也是一样吗? 其实也不用管这些细枝末节的运算细节, 编程中几乎用不到, 通常只会将%
用于正整数, 这时这个行为在任何编程语言中都是一致的, 不会有什么差别, 其他的细节, 记还容易记错go
语言多次import
一个包, 这个包会被多次初始化吗? 我认为只初始化一次比较合理, 不然没办法共享变量了go
语言中len
函数返回的是一个有符号类型, 有符号类型使逆序遍历时, 不会转换为最大的正整数而发生panic
. 其实也对无符号数, 太容易变成最大的正整数了, 非常容易出错, 这有可能也是java
只用有符号数的原因吧, 所以只在数值的大小没用的时候才使用无符号数, 例如位运算go
语言中,rune
变量存的是符号的码表值, 还是经过UTF-8
编码后的值呢? 应该是码表值.java
中也是一样go
语言除以float
变量的0
值, 居然不报错, 真是离谱, 但是直接除以0.0
又会报错, 就离谱go
语言短变量声明的默认类型为int
和float64
go
语言true
不会隐式转换为1,false
也不会隐式转换为0, 反之亦然,java
也是这样go
语言中字符串是不可变的, 跟java
是一样的, 为什么它们都是不可变的呢? 我只能想到一个原因共享提升性能go
中字符串的len
返回的是字节的个数,java
中返回的字符的个数- 字符串中汉字的自然编码顺序等于拼音的顺序吗? 应该是不等于, 有些非常少用的汉字, 拼音靠前, 不会在65536个常用字符中, 常用字符的编码应该是很小的
go
中字符串不能简单的看成字符的数组, 字符串是不可变的, 而数组是会相互影响的go
的字符串支持[]
来取值,java
不支持[]
, 但有charAt
函数go
支持`扩起来的原生字符串,java
支持吗UTF-8
大小为1
到4
字节, 那对于4位的unicode
码点, 是不是有可能放不下呢?go
语言字符串不是rune
的数组, 直接就是UTF-8
编码好的字节流,, 跟java
完全不一样. 那怎么取第几个字节呢? 使用utf8.DecodeRuneInString
来解码, 或使用range
,range
自动就是按字符读取的, 那我就想取第i
个字符呢? 可以将string
转为rune
数组, 这丫就可以取了, 感觉go
语言使用string
还是好没必要, 几乎每什么用. 那要向java
那样使用字符串, 还要利用string
来赋值, 再转乘[]rune
来使用,rune
可以用字符字面量,unicode
码点, 对于小于256的字符, 还可以使用\x
, 好像每啥用,string
可以字符串字面量,UTF-8
字节序列, 和unicode
码点序列go
语言和c
语言都有scanf
, 但java
没有, 但java
应该有从字符串提取出值的办法go
中每种常量的潜在类型都是基础类型, 那是说只要潜在类型为基础类型的, 就能是常量吗?go
中const
和type
都可以使用括号来同时定义多个go
中常量间的所有算术运算, 逻辑运算和比较运输的结果也是常量, 对于常量的类型转换操作或部分函数也是常数, 常数就是提升了一点可读性和性能, 好像也没有什么大作用go
中通过%T
来打印类型,java
可以通过打印类名go
语言常量也一些简化的赋值方式, 还有一个作用相当有限的itoa
关键字来赋值, 感觉没有什么必要go
中字面量称为无类型常量, 无类型常量可以自己转为声明的类型, 如果没有声明类型, 就是go
定义的规则指定的类型, 算术运算也是同理, 这跟c
和java
中字面量有默认的类型不同- 零大小的数组有什么用? 零大小的接口和数据结构对于go语言好像有bug
go
中var a [3]int
和var b [4]int
,a
和b
是不同类型, 不能相互赋值, 在c
语言中也是一样. 但在java
中长度不会导致数组类型不一样, 而且定义数组变量时, 也没有指定长度.java
中数组怎么初始化的呢? 会有默认值吗go
语言中数组的相等判断非常奇怪, 只有数据类型, 长度, 且数据类型能比较的情况下, 数组才能比较, 否则会报错. 当数据长度, 且数据值相等时, 才相等. 能比较的数据结构, 不是只有基础数据结构, 结构体支持吗go
语言传递数组时, 是会挨个复制数组值的, 这个跟c
和java
都是不一样的. 可以说是多了一种防止修改数组的方式go
对指向数组的指针是可以直接便利的,ptr[i]
和(*ptr)[i]
的效果是一样的, 在range
中ptr
和(*ptr)
也是一样的, 这很离谱go
语言数组和slice
的语法很难区分, 只有定义的时候,slice
的[]
不写值, 而数组是需要指定大小或者...
.len
和cap
既可以运用于数组, 也可以用于slice
.s[i:j]
切片操作中j
可以超过len
, 但不能超过cap
, 真的无语, 切片操作可以用在数组和slice
上, 切出来是slice
go
语言的slice
不支持比较,java
的是支持的,go
语言面向对象的特性太差了. 是怕slice
自己引用自己吗,java
不也有这种问题吗, 那为什么java
可以比较.- 不要用可变类型作为
map
的key
, 无论是go
还是java
,key
如果变了,hash没变
会导致位置不变, 如果引用了同一个key
, 会导致判断不出key
已经存在, 或者相等. 放入map
后,key
的hash
值应该是不会在变了, 不然还要watch
,key
的值变没有, 太消耗性能了, 这只是一个推测还没有自我验证过. - 这本书说了两个理由, 都无法说明
go
的slice
为啥不能比较, 吐了 slice
只能和nil
比较, 可以用[]int(nil)
或nil
来赋值给以slice
变量,nil
可以赋值给指针和引用类型, 接口类型算引用类型吗, 结构体可以用nil
赋值吗go
中len
和cap
为0的slice
, 就可以为nil
, 也可以不为nil
. 为nil
的sclie
底层没有引用数组,go
中nil
有什么用呢???go
的printf
怎么用的, 数组怎么打印, 类型怎么打印go
语言中copy
函数就只能用于数组的复制吗? 能使用的范围太小了吧,append
也只能用于slice
吗go
语言中var x, y []int
可以声明多个slice
, 那声明多个指针呢? 指针能var x, y *int
这么写吗go
语言支持可变参数,java
支持吗? 可变参数可以用slice
来实现, 那直接用slice
来传参数不行吗, 就为了调用函数时写起来好看吗- go程序设计语言没有教
delete
的用法, 无语, 增删改查, 不应该是最重要的吗,go
中数组删除是自己用分片来实现吗?delete
是用来删除map
中的元素的 go
语言中cap
有必要让go
语言使用者感知到吗? 真不知道有什么用,java
是没有让使用者感知到的go
的map
中key
必须是支持==
的, 可是go
中结构体支持==
吗, 我认为应该必须得支持, 不然map
也太鸡肋了, 确认了, 结构体是支持==
go
中在map
中取值时, 如果key
不存在, 返回的是零值, 其实也只能这样, 总不能报错吧go
中不能对map
中的value
取地址,value
是会移动, 地址可能会随时失效. 地址的抽象程度太低了, 很容易受别的因素变化go
语言中map
的零值是nil
, 这时map
没有引用任何哈希表,nil
的slice
和空的slice
几乎没有差别,nil
的map
无法添加值, 毕竟append
函数是有能力自己创建新slice
的go
语言中map
是无法比较的, 除了和nil
, 这个是和slice
是一致的.java
中List
和Map
是能比较的吗go
语言中len
函数可以运用于map
go
中0个值的聚合体有什么用呢?go
语言中点操作符可以用于指向结构体的指针, 这是什么骚操作, 直接用->
不好吗, 这样很容易把结构体和结构体指针弄混,go
语言中指针是不能用->
, 好像都没有这个操作符.go
中调用函数返回的是值, 并不是一个可取地址的变量. 头一次在编程语言中听说这种说法.c
语言会有这种问题吗? 应该会有吧, 没有验证过go
中定义结构体时, 成员的顺序不同, 会导致定义的结构体不同, 那这种不同体现在哪里呢? 不是有类型名称来做区分了吗? 简直无法理解go
语言中结构体的导出, 也是根据首字母的大小写来判断的, 导出能在包外访问, 没有导出的, 只能在包内访问go
语言中一个命名为S的结构体类型不能再包含S类型的成员. 但是S类型的结构体可以包含*S
指针类型的成员,c
和java
是怎样的呢go
中为什么结构体字面量可以取地址, 而整数不行? 看不懂看不懂go
语言中结构体的比较, 限制好大, 而且非常不灵活.go
要求结构体的所有成员都必须可以比较, 而且必须全部相等, 这比java
差太多了go
的匿名成员机制, 也没有啥用呀, 就是为了使用成员时不用写出中间的成员. 如果有多个相同类型的成员呢? 而且结构体的命名还会影响导出, 又是一个鸡肋的东西. 唯一的用处可以获得匿名成员的方法, 其实可以把匿名成员当成继承来用- 编程语言中第一类值或第一公民, 指的是能被赋值, 拥有类型的类型,
go
中函数是有类型的,c
也是,java
中函数只能放在class
中, 不能被赋值啥的 go
中函数值的零值是nil
, 当调用nil
时会发生panic
, 同时函数值是不能比较的, 只能和nil
比较. 那是不是go
中每种类型都要记一下能不能比较呢, 感觉容易出现混乱. 现在不能比较的是slice
,map
, 函数- 匿名函数可以访问外部函数的变量, 有点像
java
的匿名类, 当访问外部变量这种用法, 还是有些高级, 不知到该用在什么地方, 不用这种高级用法, 用传参数可以吗 - 闭包是什么意思,
go
中函数值也被称为闭包, 闭包是一种很底层的概念了吧 go
程序设计语言举的例子都不简单, 真的垃圾go
中函数值使用外部的变量的时, 非常容易出现bug
, 使用所有值都是地址, 又是一个坑呀go
中Printf
是可变参数吗, 为什么它可以任意类型呢? 自己可变参数只能是同一类型的,Printf
用的是interface{}
类型, 这个类型有点像java
中的object
- 可变参数可以用
slice
来实现, 那多一种语法其实也没有什么必要, 可以看作是一种语法糖 go
语言中defer
的作用跟finally
差不多, 但是使用的位置是不同的, 同时defer
调用的顺序是相反的.defer
有一个很独特的操作func ()()
, 它只会在函数结束后调用最后一个函数, 前面的函数会在使用defer
的地方被调用. 这就实现了, 使用前调用和使用后调用的结果, 很像aop
,defer
能实现的东西finally
也能实现, 但是defer
的写法更好看一些- 什么是异常呢? 就是调用者本应该遵守规则去使用某个函数, 但使用时却违反规则去使用. 什么时候使用
err
, 调用者遵守了规则, 但是实现者发现因为某种原因, 无法给出正确的结果. 说到底, 就是谁负责. go
中结构体的成员和方法共用一个命名空间, 就是成员和方法的名称不能相同.java
中成员方法应该是可以同名的吧go
中方法可以被声明到任意类型, 只要不是一个指针或者一个interface
,interface
不能有方法我能理解, 毕竟自己定义时已经写了, 为什么指针也不能有方法呢? 不明白, 也许设计如此吧go
中调用方法是不是有两种方式, 一种是对象.
语法, 另一种是函数类似的调用, 用第一参数作为对象, 应该是有两种的. 为什么有两种呢? 第一种是第二种的语法糖, 这是我认为的, 其实也是非常合理的go
语言中指针可以调用类型的方法, 类型也可以调用指针的方法前提是它是变量, 不是字面量, 那为什么地址字面量可以调用类型的方法呢? 到底什么是字面量啊), 这当中go
会存在隐式转换, 语法糖太多了, 让初学者很困惑, 垃圾. 如果指针和类型, 都声明了同名称方法, 这样会有什么后果, 或者这样是在同一个命名中的. 应该是在同一个命名空间中的吧. 验证出来, 是在同一个命名空间中的, 这样挺合理, 不然就太混乱了go
语言允许类型的nil
来调用方法, 跟java
不一样,java
会报空指针异常的go
中结构体除了能内嵌类型, 还能内嵌指针, 内嵌指针有什么用呢? 其实没有什么区别, 除了利用指针可以共享同一个对象.go
中除了匿名函数, 还有匿名结构, 但是匿名结构没有地方也方法, 不像java
匿名类可以在块中写方法. 但是go
匿名结构中匿名成员能带来一些方法, 算是一种有效的弥补手段吧. 匿名函数和匿名结构, 一般什么时候会用呢? 一个函数或结构只会被用一次时, 可以懒得取方法, 还是非常有用的, 取名字可太麻烦了go
中接口是隐式实现的,java
中需要自己写明, 这两个有什么区别呢? 隐式可以让旧的类实现新实现的方, 但是java
可以用适配器模式来实现, 说到底, 其实也没有啥区别是吗? 就是稍微方便点- 面向接口编程是指导思想,
LSP
是面向接口编程的实现的要求和规则 go
中for
循环对于string
有特殊的操作,slice
和string
也有特殊操作,[]byte("霄剑")
可以直接变成UTF8
编码的字节slice
go
中结构体和接口都有内嵌语法, 还有别的类型有这种语法吗?go
值接收器和指针接收器有很多不同的, 太坑了. 既然值接收器会生成一个指针接收器的方法, 那为啥用指针类型调用方法时, 还要编译器来解引用呢? 不是已经生成了指针接收器的方法了吗? 搞不懂go
语言中匿名结构体可以有相同名称的方法, 例如String
方法, 如果有两个匿名结构体都有String
方法, 编译会报错, 这个有点像多继承带来的问题go
语言结构体字面量可以取地址,c
语言不行, 我认为这应该又是go
语言的语法糖go
中接口是可以比较的, 但是接口的动态类型不能比较的话, 会报panic
, 还有一个问题, 接口比较有什么用呢? 这又是什么骚操作go
中实现排序需要实现三个方法,java
中只需要实现一个方法,c
语言中是怎么实现的呢?go
中类型断言和转型的语法很像.x.(T)
和T(x)
, 真的像. 类型断言中x
只能是接口,T
可以是接口或者类型. 当x
为nil
时, 会报panic
. 类型断言是反多态的, 在java
中是非常不值得推荐的.go
却非常推荐, 我觉得应该时不值得推荐的, 毕竟违反了多态,当然特例情况也是存在的, 具体类型有更好解决方案时, 可以使用断言- 子类型多态和非参数多态(可识别联合), 子类型多态是抽象, 隐藏细节, 而非参数多态是将接口强制转成特定类型, 那在
java
中是不是把object
接收值再转成各种类型, 只能说很像, 这种做法面向对象不是不提倡吗? 也不是面向对象编程的使用接口的目的, 真是各种用法都有, 只要有用就行. 这种用法在go
语言中有一种语法来支持, 叫类型开关,x.(type)
,java
中有类似的语法吗? - 类型开关在单一类型的
case
内部, 才会进行类型转换, 在其他情况下都是没有转换之前的值. 行为挺奇怪的
-------------本文结束感谢您的阅读-------------