Golang 学习 - 01

该博客围绕Go语言展开,介绍了信号相关内容,包括常用信号及Go实现,如创建管道连接os.Signal、循环捕获和处理信号;还讲解了测试框架,如创建测试文件和函数、记录测试信息等;此外,阐述了Web基础,涉及hello world、表单处理,包括防止跨站攻击、文件上传等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • 信号
  • 测试
  • web hello world
  • 表单处理

1. 信号

1.1 常用信号

信号动作说明
SIGUP1Term终端连接中断
SIGINT2Term用户发送INTR:ctrl+c
SIGQUIT3Core用户发送QUIT:ctrl+/
SIGKILL9Term无条件结束,无法捕获
SIGTERM15Term结束,可被捕获

1.2 go实现

  • 创建管道,连接os.Signal
  • os.Signal Notify 指定信号
  • while :=<-c 循环捕获
  • switch/case 处理信号
	c := make(chan os.Signal, 1)
	signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)

	for {
		s := <-c
		fmt.Println("recv sig")
		switch s {
		case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
			fmt.Println("quit ...")
			return
		case syscall.SIGHUP:
			fmt.Println("sighup ...")
		default:
			fmt.Println("default ...")
			return
		}
	}

2. 测试

2.1 测试框架

  • 创建测试
  1. 创建后缀名为XX_test.go 的文件

  2. 创建函数 TestXXX(test *testing.T){}

  3. 记录测试信息

    log记录信息,Fatalf用于记录严重错误,FailNow标记错误信息并立刻退出,

func TestRunSampleA(t *testing.T) {
	t.Log("test a")
	for i := 0; i != 10; i++ {
		if i > 6 && i <= 8 {
			// 记录错误信息
			t.Errorf("err output %d", i)
			//标记当前错误
			t.Fail()
		} else if i > 8 {
			// 记录严重信息
			t.Fatalf("curical output %d", i)
			//标记错误并退出
			t.FailNow()
		} else {
			//记录信息
			t.Logf("curr output %d", i)
		}
	}
	t.Log("expect success return ..")
}
  1. 其他测试

    Skip 跳过当前测试 Parallel开启并行测试,Example启用一条样例测试

func ExampleTestA(){
	fmt.Println("hello")
	//Output:hello a
}

3.web基础

3.1 hello world

func main() {
	http.HandleFunc("/",sayHello)						//设置路由
	err := http.ListenAndServe(":9090",nil)		//设置监听
	if err!=nil{
		log.Fatal("listen and serve ",err)
	}

}

func sayHello(response http.ResponseWriter, request *http.Request) {
	//	sample
	//	http://localhost:9090
	//	http://localhost:9090/?url_long=111&url_long=222
	request.ParseForm()											//解析参数
	fmt.Println(request.Form)									//表单
	fmt.Println("path	", request.URL.Path)				//路由地址
	fmt.Println("scheme	",request.URL.Scheme)			//携带参数
	fmt.Println(request.Form["url_long"])
	for k,v := range request.Form{								//循环输出
		fmt.Println("key	",k)
		fmt.Println("value	",v)
	}
	fmt.Fprintf(response,"hello go lang! ")
}

3.2 表单

  • 表单方法
func login(response http.ResponseWriter, request *http.Request) {
	fmt.Println("method	", request.Method)
	if request.Method == "GET" {
		t, _ := template.ParseFiles("login.gtpl")
		log.Println(t.Execute(response, nil))
	} else {
		request.ParseForm()
		fmt.Println("username	", request.Form["username"])
		fmt.Println("password	", request.Form["password"])
	}
}

  • 字段解析 正则表达式 略

  • 防止跨站攻击

fmt.Println("username ",template.HTMLEscapeString(request.Form.Get("username")))
fmt.Println("password ",template.HTMLEscapeString(request.Form.Get("password")))
template.HTMLEscape(response,[]byte(request.Form.Get("username")))
  • 防止多次递交表单

    增加token生成和检测,在gtpl中增加token的隐藏字段

func login(response http.ResponseWriter, request *http.Request) {
	fmt.Println("method	", request.Method)
	if request.Method == "GET" {
		currtime := time.Now().Unix()
		h := md5.New()
		io.WriteString(h, strconv.FormatInt(currtime,10))
		token := fmt.Sprintf("%x",h.Sum(nil))
		t, _ := template.ParseFiles("login.gtpl")
		log.Println(t.Execute(response, token))
	} else {
		request.ParseForm()
		//防止跨域攻击
		token :=request.Form.Get("token")
		if token !=""{
			//test token
			fmt.Println("token", token)
		}	else{
			// invalid !
			fmt.Println("no token")
		}
		fmt.Println("username ",template.HTMLEscapeString(request.Form.Get("username")))
		fmt.Println("password ",template.HTMLEscapeString(request.Form.Get("password")))
		template.HTMLEscape(response,[]byte(request.Form.Get("username")))
	}
}
  • 处理文件上传

    • 为表单增加属性, enctype=“multipart/form-data”
    • 表单处理的实现
      关键函数 : request.ParseMultipartForm,
      f,err := os.OpenFile("./test/"+handler.Filename,os.O_WRONLY|os.O_CREATE,0666)
func upload(response http.ResponseWriter, request *http.Request) {
	fmt.Println("method",request.Method)
	if request.Method =="GET"{
		currtime := time.Now().Unix()
		h:= md5.New()
		io.WriteString(h,strconv.FormatInt(currtime,10))
		token :=fmt.Sprintf("%x",h.Sum(nil))

		t,_ := template.ParseFiles("upload.gtpl")
		t.Execute(response,token)
	} else {
		request.ParseMultipartForm(32<<20)
		//表示最大传输大小,超出大小将转存到系统临时文件
		file,handler,err := request.FormFile("uploadfile")
		if err != nil{
			fmt.Println(err)
			return
		}
		defer file.Close()
		fmt.Fprintf(response,"%v", handler.Header)
		fmt.Println("current upload filename ",handler.Filename)
		f,err := os.OpenFile("./test/"+handler.Filename,os.O_WRONLY|os.O_CREATE,0666)
		if err != nil{
			fmt.Println("err 123",err)
			return
		}
		defer f.Close()
		io.Copy(f,file)
	}
}
  • 客户端实现, 略
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值