В вашем случае возможный (но не приятный) выбор использует контекст:
type User struct {
name string
uid int64
}
func main() {
user := &User{
name: "hezhixiong",
uid: int64(58741634),
}
ctx := context.WithValue(context.Background(), "name", user.name)
ctx = context.WithValue(ctx, "uid", user.uid)
ctx = context.WithValue(ctx, "user", user)
go SafeFunc(test1, ctx)
go SafeFunc(test2, ctx)
go SafeFunc(test3, ctx)
go SafeFunc(test4, ctx)
for {
}
}
func test1(ctx context.Context) {
panic("test1")
}
func test2(ctx context.Context) {
name := ctx.Value("name").(string)
panic(name)
}
func test3(ctx context.Context) {
name := ctx.Value("name").(string)
uid := ctx.Value("uid").(int64)
panic(fmt.Sprintln(name, uid))
}
func test4(ctx context.Context) {
user := ctx.Value("user").(*User)
panic(user)
}
// SafeFunc safe function call
func SafeFunc(f func(context.Context), ctx context.Context) {
defer func() {
if r := recover(); r != nil {
fmt.Println(r)
}
}()
f(ctx)
}
В нашем производстве мы обычно деформируем вход и выход следующим образом:
func test(in *input) (out *output) {
// parse in
// ... do something
// build out
}