分享
  1. 首页
  2. 文章

golang复习

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

1. 利用defer、recover来实现try...catch

func Try(fun func(), handler func(interface{})) {
 defer func() {
 if err := recover(); err != nil {
 handler(err)
 }
 }()
 fun()
}
func main() {
 Try(func() {
 panic("foo")
 }, func(e interface{}) {
 print(e)
 })
}

2. 关于error的一个程序

error是一个类型,类似于string,error也可以定义自己的类型

package main
import "errors"
import "fmt"
// By convention, errors are the last return value and
// have type `error`, a built-in interface.
func f1(arg int) (int, error) {
 if arg == 42 {
 // `errors.New` constructs a basic `error` value
 // with the given error message.
 return -1, errors.New("can't work with 42")
 }
 // A nil value in the error position indicates that
 // there was no error.
 return arg + 3, nil
}
// It's possible to use custom types as `error`s by
// implementing the `Error()` method on them. Here's a
// variant on the example above that uses a custom type
// to explicitly represent an argument error.
type argError struct {
 arg int
 prob string
}
func (e *argError) Error() string {
 return fmt.Sprintf("%d - %s", e.arg, e.prob)
}
func f2(arg int) (int, error) {
 if arg == 42 {
 // In this case we use `&argError` syntax to build
 // a new struct, supplying values for the two
 // fields `arg` and `prob`.
 return -1, &argError{arg, "can't work with it"}
 }
 return arg + 3, nil
}
func main() {
 // The two loops below test out each of our
 // error-returning functions. Note that the use of an
 // inline error check on the `if` line is a common
 // idiom in Go code.
 for _, i := range []int{7, 42} {
 if r, e := f1(i); e != nil {
 fmt.Println("f1 failed:", e)
 } else {
 fmt.Println("f1 worked:", r)
 }
 }
 for _, i := range []int{7, 42} {
 if r, e := f2(i); e != nil {
 fmt.Println("f2 failed:", e)
 } else {
 fmt.Println("f2 worked:", r)
 }
 }
 // If you want to programmatically use the data in
 // a custom error, you'll need to get the error as an
 // instance of the custom error type via type
 // assertion.
 _, e := f2(42)
 if ae, ok := e.(*argError); ok {
 fmt.Println(ae.arg)
 fmt.Println(ae.prob)
 }
}

3. timer和ticker都是可以停止的

package main
import (
	"fmt"
	"time"
)
func main() {
	ticker := time.NewTicker(time.Millisecond * 500)
	go func() {
		for t := range ticker.C {
			fmt.Println("ticker is at ", t)
		}
	}()
	time.Sleep(time.Millisecond * 1500)
	ticker.Stop()
	fmt.Println("ticker stopped")
}
package main
import (
	"fmt"
	"time"
)
func main() {
	timer1 := time.NewTimer(time.Second * 2)
	<-timer1.C
	fmt.Println("timer1 expired.")
	timer2 := time.NewTimer(time.Second * 1)
	go func() {
		<-timer2.C
		fmt.Println("timer2 expired.")
	}()
	ok := timer2.Stop()
	if ok {
		fmt.Println("timer2 stopped.")
	}
}

4. 一个比较复杂的channel的例子

package main
import (
	"fmt"
	"math/rand"
	"sync/atomic"
	"time"
)
type readOp struct {
	key int
	resp chan int
}
type writeOp struct {
	key int
	val int
	resp chan bool
}
func main() {
	var ops int64 = 0
	reads := make(chan *readOp)
	writes := make(chan *writeOp)
	go func() {
		var state = make(map[int]int)
		for {
			select {
			case read := <-reads:
				read.resp <- state[read.key]
			case write := <-writes:
				state[write.key] = write.val
				write.resp <- true
			}
		}
	}()
	for r := 0; r < 100; r++ {
		go func() {
			for {
				read := &readOp{
					key: rand.Intn(5),
					resp: make(chan int)}
				reads <- read
				<-read.resp
				atomic.AddInt64(&ops, 1)
			}
		}()
	}
	for w := 0; w < 10; w++ {
		go func() {
			for {
				write := &writeOp{
					key: rand.Intn(5),
					val: rand.Intn(100),
					resp: make(chan bool)}
				writes <- write
				<-write.resp
				atomic.AddInt64(&ops, 1)
			}
		}()
	}
	time.Sleep(time.Second)
	opsFinal := atomic.LoadInt64(&ops)
	fmt.Println("ops:", opsFinal)
}
5. sort包封装了一些常用的排序方法,用起来还是很方便的
package main
import "fmt"
import "sort"
func main() {
	strs := []string{"c", "a", "b"}
	sort.Strings(strs)
	fmt.Println("Strings:", strs)
	ints := []int{7, 2, 4}
	sort.Ints(ints)
	fmt.Println("Ints: ", ints)
	s := sort.IntsAreSorted(ints)
	fmt.Println("Sorted: ", s)
}

6. slice的引用特性

package main
import (
	"fmt"
)
func main() {
	array := make([]int, 0, 3)
	array = append(array, 1)
	a := array
	b := array
	a = append(a, 2)
	b = append(b, 3)
	fmt.Println(a)
}




结果是什么呢?答案揭晓,输出是"[1 3]"。

就我的理解,slice 是一个{指向内存的指针,当前已有元素的长度,内存最大长度}的结构体,其中只有指向内存的指针一项是真正具有引用语义的域,另外两项都是每个 slice 自身的值。因此,对 slice 做赋值时,会出现两个 slice 指向同一块内存,但是又分别具有各自的元素长度和最大长度。程序里把 array 赋值给 a 和 b,所以 a 和 b 会同时指向 array 的内存,并各自保存一份当前元素长度 1 和最大长度 3。之后对 a 的追加操作,由于没有超出 a 的最大长度,因此只是把新值 2 追加到 a 指向的内存,并把 a 的"当前已有元素的长度"增加 1。之后对 b 进行追加操作时,因为 a 和 b 各自拥有各自的"当前已有元素的长度",因此 b 的这个值依旧是 1,追加操作依旧写在 b 所指向内存的偏移为 1 的位置,也就复写了之前对 a 追加时写入的 2。

为了让 slice 具有引用语义,同时不增加 array 的实现负担,又不增加运行时的开销,似乎也只能忍受这个奇怪的语法了。




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

本文来自:开源中国博客

感谢作者:壬癸甲乙

查看原文:golang复习

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

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

用户登录

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

今日阅读排行

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

一周阅读排行

    加载中

关注我

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

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

给该专栏投稿 写篇新文章

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

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