zoukankan      html  css  js  c++  java
  • SpecialPrint特殊的输出结果

    SpecialPrint特殊的输出结果

    循环range问题

    • 解答

      这样的写法初学者经常会遇到的,很危险! 与Java的foreach一样,都是使用副本的方式。所以m[stu.Name]=&stu实际上一致指向同一个指针, 最终该指针的值为遍历的最后一个struct的值拷贝

    package main
    
    import "fmt"
    
    type student struct {
    	Name string
    	Age  int
    }
    
    func main() {
    	m := make(map[string]*student)
    	stus := []student{
    		{Name: "zhou", Age: 24},
    		{Name: "li", Age: 23},
    		{Name: "wang", Age: 22},
    	}
    	// 错误写法
    	for _, stu := range stus {
    		m[stu.Name] = &stu
    	}
    
    	for _, stu := range stus {
    		stu.Age = stu.Age + 10
    	}
    
    	for k, v := range m {
    		println(k, "=>", v.Age, v.Name)
    	}
    
    	fmt.Println("================")
    
    	//正确
    	for i := 0; i < len(stus); i++ {
    		m[stus[i].Name] = &stus[i]
    	}
    	for k, v := range m {
    		println(k, "=>", v.Name, v.Age)
    	}
    }
    
    # 输出
    zhou => 22 wang
    li => 22 wang
    wang => 22 wang
    ================
    zhou => zhou 24
    li => li 23
    wang => wang 22
    

    defer执行顺序

    • 解答

      defer 是后进先出。 协程遇到panic时,遍历本协程的defer链表,并执行defer。在执行defer过程中,遇到recover则停止panic,返回recover处继续往下执行。如果没有遇到recover,遍历完本协程的defer链表后,向stderr抛出panic信息。从执行顺序上来看,实际上是按照先进后出的顺序执行defer

    package main
    
    import (
    	"fmt"
    	"log"
    )
    
    func main() {
    	defer_call()
    }
    
    func defer_call() {
    	defer func() { fmt.Println("打印前") }()
    	defer func() { fmt.Println("打印中") }()
    	defer func() { fmt.Println("打印后") }()
    
    	panic("触发异常")
    }
    
    # 输出
    打印后
    打印中
    打印前
    panic: 触发异常
    
    goroutine 1 [running]:
    main.defer_call()
            D:/gohere/go-newbase/test_go/for/one/main.go:16 +0x85
    main.main()
            D:/gohere/go-newbase/test_go/for/one/main.go:8 +0x27
    exit status 2
    

    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("10", a, b))
    	a = 0
    	defer calc("2", a, calc("20", a, b))
    	b = 1
    }
    
    # 输出
    10 1 2 3
    20 0 2 2
    2 0 2 2
    1 1 3 4
    

    go执行的随机性和闭包

    • 解答

      其中A:输出完全随机,取决于goroutine执行时i的值是多少;
      而B:一定输出为0~9,但顺序不定。

      第一个go func中i是外部for的一个变量,地址不变化,但是值都在改变。

      第二个go func中i是函数参数,与外部for中的i完全是两个变量。
      尾部(i)将发生值拷贝,go func内部指向值拷贝地址。

      所以在使用goroutine在处理闭包的时候,避免发生类似第一个go func中的问题。

    package main
    
    import (
    	"fmt"
    	"runtime"
    	"sync"
    )
    
    func main() {
    	runtime.GOMAXPROCS(1)
    	wg := sync.WaitGroup{}
    	wg.Add(20)
    	for i := 0; i < 10; i++ {
    		go func() {
    			fmt.Println("A: ", i)
    			wg.Done()
    		}()
    	}
    	for i := 0; i < 10; i++ {
    		go func(i int) {
    			fmt.Println("B: ", i)
    			wg.Done()
    		}(i)
    	}
    	wg.Wait()
    }
    
    # 输出
    B:  9
    A:  10
    A:  10
    A:  10
    A:  10
    A:  10
    A:  10
    A:  10
    A:  10
    A:  10
    A:  10
    B:  0
    B:  1
    B:  2
    B:  3
    B:  4
    B:  5
    B:  6
    B:  7
    B:  8
    

    go组合继承

    • 解答

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

    package main
    
    import "fmt"
    
    type People struct{}
    
    func (p *People) ShowA() {
    	fmt.Println("showA-People")
    	p.ShowB()
    }
    func (p *People) ShowB() {
    	fmt.Println("showB-People")
    }
    
    type Teacher struct {
    	People
    }
    
    func (t *Teacher) ShowB() {
    	fmt.Println("teacher showB")
    }
    
    func main() {
    	t := Teacher{}
    	t.ShowA()
    }
    
    # 输出
    showA-People
    showB-People
    

    select随机性

    • 解答

      select会随机选择一个可用通用做收发操作。 单个chan如果无缓冲时,将会阻塞。但结合 select可以在多个chan间等待执行。有三点原则: select 中只要有一个case能return,则立刻执行。 当如果同一时间有多个case均能return则伪随机方式抽取任意一个执行。 如果没有一个case能return则可以执行”default”块。

    package main
    
    import (
    	"fmt"
    	"runtime"
    )
    
    func main() {
    	runtime.GOMAXPROCS(1)
    	int_chan := make(chan int, 1)
    	string_chan := make(chan string, 1)
    	int_chan <- 1
    	string_chan <- "hello"
    	select {
    	case value := <-int_chan:
    		fmt.Println("int:", value)
    	case value := <-string_chan:
    		fmt.Println("string:", value)
    	}
    }
    
    # 输出
    都有可能
    

    make默认值和append(这个很奇怪)

    package main
    
    import (
    	"fmt"
    )
    func main() {
    	s := make([]int, 5)
    	s = append(s, 1, 2, 3)
    	fmt.Println(s)
    }
    
    # 输出
    [0 0 0 0 0 1 2 3]
    

    interface内部结构

    • 解答

      空接口是 var i interface{},这个不是

    package main
    
    import (
        "fmt"
    )
    
    type People interface {
        Show()
    }
    
    type Student struct{}
    
    func (stu *Student) Show() {
    
    }
    
    func live() People {
        var stu *Student
        return stu
    }
    
    func main() {
        if live() == nil {
            fmt.Println("AAAAAAA")
        } else {
            fmt.Println("BBBBBBB")
        }
    }
    
    # 输出
    BBBBBBB
    
  • 相关阅读:
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    Cookie、Session、Token
    Spark SQL
  • 原文地址:https://www.cnblogs.com/maomaomaoge/p/14129740.html
Copyright © 2011-2022 走看看