上下文(context)的使用·数据传递

package main

import (
   "context"
   "fmt"
   "net/http"
)

// 本函数演示如何将数据附加到上下文
func func1(ctx context.Context) {
   // 继续将数据(key/value)附加到上下文
   ctx = context.WithValue(ctx, "name", "张三")
   ctx = context.WithValue(ctx, "gender", "男")
   ctx = context.WithValue(ctx, "age", 18) // 重要说明:该数字是int类型,不是int64类型,类型断言时要注意

   // 继续将上下文作为参数传递
   func2(ctx)
}

// 本函数演示如何从上下文里取出数据
func func2(ctx context.Context) {
   // 从上下文取出数据
   writer, _ := ctx.Value("writer").(http.ResponseWriter) // Value()方法返回值是any类型,需要类型断言才能使用
   name, _ := ctx.Value("name").(string)                  // Value()方法返回值是any类型,需要类型断言才能使用
   gender, _ := ctx.Value("gender").(string)              // Value()方法返回值是any类型,需要类型断言才能使用
   age, _ := ctx.Value("age").(int)                       // Value()方法返回值是any类型,需要类型断言才能使用

   // 在页面上输出内容
   str := fmt.Sprintf("俺叫%s%s),今年%d岁。", name, gender, age)
   _, _ = writer.Write([]byte(str)) // 俺叫张三(男),今年18岁。
}

func main() {
   // 演示地址:http://localhost:8080/demo.html
   http.HandleFunc("/demo.html", func(writer http.ResponseWriter, request *http.Request) {
      requestContext := request.Context() // 获取本次请求的上下文
      // requestContext := context.Background() // 也可以不使用本次请求的上下文,而是创建一个非nil的空上下文

      // 将数据(key/value)附加到上下文
      requestContext = context.WithValue(requestContext, "writer", writer)
      requestContext = context.WithValue(requestContext, "request", request)

      // 将上下文作为参数传递
      func1(requestContext)
   })

   // 启动HTTP服务器
   err := http.ListenAndServe(":8080", nil)
   if err != nil {
      panic("启动HTTP服务器失败:" + err.Error())
   }
}

// ========== 总结 ========== //
// 1、将数据附加到上下文:ctx = context.WithValue(ctx, "key", "value"),value的数据类型为any,故可附加任意数据类型到上下文。
// 2、从上下文里取出数据;value := ctx.Value("key"),方法返回值是any类型,故如有需要可使用类型断言。
// 3、Go官方建议如果自定义函数的形参有context.Context类型,那么该参数应该放在第一位,且参数名通常为ctx,如下面的代码:
//    func DoSomething(ctx context.Context, arg Arg) error {
//        // ... use ctx ...
//    }

Copyright © 2024 码农人生. All Rights Reserved