分享
  1. 首页
  2. 文章

golang基本题目相关

强某某 · · 965 次点击 · · 开始浏览
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

package main
import (
 "fmt"
 "runtime"
 "strings"
 "sync"
 "time"
 "unsafe"
)
//死锁
func main01() {
 t := time.NewTicker(time.Second * 5)
 // defer t.Stop() 解决死锁方案,在此处用defer关闭
 for range t.C {
 fmt.Println(1)
 //stop关闭信号,不关闭通道通信,导致死锁
 // t.Stop()
 }
}
//字符串处理
func main02() {
 //只要字符串包含fedabc任何一个就去掉,而且和顺序无关,所以整体都被去除了
 s := strings.TrimRight("abcdefedcba", "fedabc")
 fmt.Printf("%q\n", s) //"" %q输出带双引号的内容
 //按照顺序删除后缀
 s1 := strings.TrimSuffix("abcdefedcbaabcdef", "abcdef")
 fmt.Println(s1) //abcdefedcba
}
//切片操作
func main03() {
 v := []int{1, 2, 3}
 //不会出现死循环 range会对数据进行拷贝
 for i := range v {
 v = append(v, i) //[1 2 3 0 1 2]
 fmt.Printf("%p\n", v) //array的地址 :slice中是array的引用,其中包含指向slice的数组len和slice的上限的指针
 fmt.Printf("%p\n", &v) //指针地址
 //所以上面两者打印不是同一个地址
 }
 fmt.Println(v)
}
func main04() {
 //rune数据类型,支持中文编码集
 r := []rune("你好")
 for _, val := range r {
 fmt.Printf("%c", val)
 }
}
func main05() {
 //string 类型 可以转成[]byte []rune
 b := []byte("hello")
 r := []rune("haha")
 // i:=[]int("sfas") 报错
 //将字符串转成整型
 // i,err:=strconv.Atoi("124")
 fmt.Println(b, r)
}
func f(a int, b int) {
 //返回拷贝成功得个数,前面是目标结构体,后面是源结构体
 val := copy(make([]struct{}, a), make([]struct{}, b))
 fmt.Printf("%d\n", val) //90
}
func main06() {
 slice := make([]struct{}, 10)
 //slice:本身存储了三个内容,array len cap 这三者都是整型,所以64位系统下,一个整型8字节 3*8=24 如果32位系统则是12
 fmt.Println(unsafe.Sizeof(slice)) //24
 //此处10指的是切片中array这个指针指向得地址存储数据所占据得大小
 //此时目标结构体最多只能放90个,所以结果是90,如果90,314换个位置,还是结果90,因为源结构体也就90个
 f(90, 314)
}
type P *int
type Q *int
func main61() {
 var p P = new(int)
 *p += 8
 var x *int = p
 var q Q = x
 *q++
 fmt.Println(*p, *q) //9 9 引用同一块内存
}
func main62() {
 m := make(map[string]int)
 m["foo"]++
 fmt.Println(m["foo"]) //1 进行初始化,m["foo"]不能存在因为int类型初始化为0
}
//错误拦截
func main07() {
 go func() {
 //如果没有错误拦截,则不一定输出多少.之后报panic异常程序终止
 defer func() {
 err := recover()
 if err != nil {
 fmt.Println(err)
 }
 }()
 panic("Boom")
 }()
 for i := 0; i < 100; i++ {
 fmt.Print(".")
 }
 fmt.Println("Done")
}
func main08() {
 defer func() { fmt.Println("1") }()
 defer func() { fmt.Println("2") }()
 defer func() { fmt.Println("3") }()
 panic("触发异常")
 /*
 3 2 1 触发异常
 遇到panic之后,后面代码都不执行了,只有所有操作出栈之后才能输出异常得警告
 */
}
type student struct {
 Name string
 Age int
}
func main09() {
 m := make(map[string]*student)
 stus := []student{
 {Name: "zhou", Age: 24},
 {Name: "li", Age: 23},
 {Name: "wang", Age: 22},
 }
 for _, stu := range stus {
 //for循环得stu必须如下重新赋值,不然指针类型赋值会把最后一次循环得付给所有value
 stu := stu
 m[stu.Name] = &stu
 }
 //这种方式则可以直接使用,不需要中间赋值一次
 // for i := 0; i < len(stus); i++ {
 // m[stus[i].Name] = &stus[i]
 // }
 for k, v := range m {
 fmt.Println(k, v)
 }
}
func main10() {
 //设置0的时候即使用最大值,其他数值都是指定使用多少个CPU
 runtime.GOMAXPROCS(1)
 wg := sync.WaitGroup{}
 wg.Add(10)
 for i := 0; i < 10; i++ {
 go func(i int) {
 fmt.Println(i)
 wg.Done()
 }(i)
 }
 //队列顺序
 // time.Sleep(time.Second) 1核时候,不加这句 9 0....8
 wg.Wait()
}
func main11() {
 a := []int{0, 1, 2, 3, 4, 5, 6, 7}
 b := a[:3]
 //这种b被另外一个切片赋值,b的容量是 a的长度-起始截取下表(此时是0,cap-low),所以b的cap是8,append一个4不会超出容量
 //而且其中array指向和a的array都是一个地址,所以b追加一个4,会覆盖a中的3
 b = append(b, 4)
 // fmt.Println(cap(b)) //8
 fmt.Println(a) //[0 1 2 4 4 5 6 7]
 fmt.Println(b) // [0 1 2 4]
}
//这样就行了
func GetValue() interface{} {
 return 1
}
// func GetValue() int {
// return 1
// }
func main12() {
 i := GetValue()
 switch i.(type) {
 case int:
 println("int") //输出int
 case string:
 println("string")
 case interface{}:
 println("interface")
 default:
 println("unknown")
 }
 //报错:断言必须是接口类型,cannot type switch on non-interface value i (type int)
}
func main13() {
 //new:创建指针 make创建都是引用类型,例如切片有容量长度等附加属性
 //list此时是指针类型 *[]int
 list := new([]int)
 // list = append(list, 1) 报错 append要求是切片,但是此时是切片指针
 *list = append(*list, 1)
 fmt.Println(list, *list) //&[1] [1]
}
func main14() {
 s1 := []int{1, 2, 3}
 s2 := []int{4, 5}
 //...叫不定参数
 // s1 = append(s1, s2)//报错
 //不定参原理等同于切片,append第二个参数必须是不定参
 s1 = append(s1, s2...)
 fmt.Println(s1)
}
func test(a ...int) {
}
//不定参
func sum(arr ...int) {
 //原理等同于切片:所以也有len cap
 fmt.Printf("%T\n", arr) //[]int
 //必须这样才能正常传参,不然传递的就只是切片而不是不定参
 test(arr...)
}
func main() {
 //可以一个参数也不传递
 sum()
}

init函数

package main
func init() {}
func init() {}
func main() {}
  • 这个程序将会正常运行
  • 一个包下不可以有两个相同名称的函数,init函数除外,编译期间,编译器会用唯一的后缀重
    写每个init函数的名称
  • 一个init函数只能执行一次,并且无法在主函数中调用init函数
func init() {
 var pcs [1]uintptr
 runtime.Callers(1, pcs[:])
 fn := runtime.FuncForPC(pcs[0])
 fmt.Println(fn.Name())
 }
 func init() {
 var pcs [1]uintptr
 runtime.Callers(1, pcs[:])
 fn := runtime.FuncForPC(pcs[0])
 fmt.Println(fn.Name())
 }

main.init.0 main.init.1
编译期间,编译器会用唯一的后缀重写每个init函数的名称

函数初始化顺序

1.jpg
  • 数据类型
package main
func A(string string) string {
return string + string
}
func B(len int) int {
return len+len
}
func C(val, default string) string {
if val == "" {
 return default
}
return val
}
  • A B 能运行
  • default 是关键字,不可以使用做变量名,string 和 len 是事先声明的标识符,可以使用,但
    是不建议使用
  • select
package main
import (
 "time"
 "fmt"
)
func A() int {
 time.Sleep(100 * time.Millisecond)
 return 1
}
func B() int {
 time.Sleep(1000 * time.Millisecond)
 return 2
}
func main() {
 ch := make(chan int, 1)
 go func() {
 select {
 case ch <- A():
 case ch <- B():
 default:
 ch <- 3
 }
 }()
 fmt.Println(<-ch)
}

输出1 或 2,管道获取到返回值后完成了主函数,主函数在接收到第一个返回值前在进行阻塞等待

  • 方法继承
package main
import "fmt"
type People struct{}
func (p *People) ShowA() {
 fmt.Println("showA")
 p.ShowB()
}
func (p *People) ShowB() {
 fmt.Println("showB")
}
type Teacher struct {
 People
}
func (t *Teacher) ShowB() {
 fmt.Println("teacher showB")
}
func main() {
 t := Teacher{}
 t.ShowA()
}

输出showA showB
这是Golang的组合模式,可以实现OOP的继承。 被组合的类型People所包含的方法虽然升
级成了外部类型Teacher这个组合类型的方法(一定要是匿名字段),但它们的方法
(ShowA())调用时接受者并没有发生变化。 此时People类型并不知道自己会被什么类型组
合,当然也就无法调用方法时去使用未知的组合者Teacher类型的功能。

  • defer调用
package main
import "fmt"
func calc(index string, a, b int) int {
 ret := a + b
 fmt.Println(index, a, b, ret)
 return ret
}
func main() {
 a := 1
 b := 2
 defer calc("1", a, calc("3", a, b))
 a = 0
 defer calc("2", a, calc("4", a, b))
 b = 1
}

输出 3 1 2 3,4 0 2 2,2 0 2 2,1 1 3 4

注意:defer calc内部的calc没有defer修饰所以会立即执行

结构体比较

package main
import "fmt"
func main() {
 sn1 := struct {
 age int
 name string
 }{age: 11, name: "qq"}
 sn2 := struct {
 age int
 name string
 }{age: 11, name: "qq"}
 if sn1 == sn2 {
 fmt.Println("sn1 == sn2")
 }
}

输出sn1 == sn2
进行结构体比较时候,只有相同类型的结构体才可以比较,结构体是否相同不但与属性类型个数有关,还与属性顺序相关。结构体相同的情况下还需要结构体属性都是可比较类型才可以使用"=="进行比较。

package main
import "fmt"
func main() {
 sn1 := struct {
 age int
 m map[string]string
 }{age: 11,m: map[string]string{"a": "1"}}
 sn2 := struct {
 age int
 m map[string]string
 }{age: 11, m: map[string]string{"a": "1"}}
 if sn1 == sn2 {
 fmt.Println("sn1 == sn2")
 }
}

编译错误,进行结构体比较时候,只有相同类型的结构体才可以比较,结构体是否相同不但与属性类型
个数有关,还与属性顺序相关。结构体相同的情况下还需要结构体属性都是可比较类型才可
以使用"=="进行比较。

总结:结构体比较,顺序不同也会不相等;
比较和成员的类型有关,例如:map是属性,地址肯定不一样的,可以通过map["具体成员"]==这样去比较,多个时候通过&&即可,否则直接比较是没法进行的


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:强某某

查看原文:golang基本题目相关

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

关注微信
965 次点击
暂无回复
添加一条新回复 (您需要 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传

用户登录

没有账号?注册
(追記) (追記ここまで)

今日阅读排行

    加载中
(追記) (追記ここまで)

一周阅读排行

    加载中

关注我

  • 扫码关注领全套学习资料 关注微信公众号
  • 加入 QQ 群:
    • 192706294(已满)
    • 731990104(已满)
    • 798786647(已满)
    • 729884609(已满)
    • 977810755(已满)
    • 815126783(已满)
    • 812540095(已满)
    • 1006366459(已满)
    • 692541889

  • 关注微信公众号
  • 加入微信群:liuxiaoyan-s,备注入群
  • 也欢迎加入知识星球 Go粉丝们(免费)

给该专栏投稿 写篇新文章

每篇文章有总共有 5 次投稿机会

收入到我管理的专栏 新建专栏