前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Golang 实用小技巧合集

Golang 实用小技巧合集

作者头像
灵雀云
发布2021-09-02 10:37:20
6080
发布2021-09-02 10:37:20
举报

以下文章来源于进击的代码 ,作者阿然

本文将分享6个 Golang 实用小技巧:

  • Go 循环跳转语句使用标签的作用之一
  • Golang IP 地址字符串整数/string int 相互转换
  • Golang 八进制 utf-8 编码转中文
  • Golang httputil 库,一行代码搞定 http 请求
  • Golang debuglog 库,调试程序时快捷查看变量值
  • go-httpbin, http 请求测试工具推荐

01

Go 循环跳转语句使用标签的作用之一

Go 中的 for 循环可以使用 continue, break 进行控制,同时也可以标签

下面看一下使用标签的一个好处

示例:Go 求 N 以内的素数

代码语言:javascript
复制
package main
 
import (
	"fmt"
)
 
func main() {
	printPrime(10)
}
 
func printPrime(maxNum int) {
next:
	for outer := 2; outer < maxNum; outer++ {
		for inner := 2; inner < outer; inner++ {
			if outer%inner == 0 {
				continue next
			}
		}
		fmt.Printf("%d\n", outer)
	}
	fmt.Println("Completed")
}

再看一下用C语言实现的(C 的 continue, break 不支持标签)

代码语言:javascript
复制
#include <stdio.h>
 
void printPrime(int maxNum)
{
	int outer, inner;
	int flag;
 
	for (outer = 2; outer < maxNum; outer++)
	{
		flag = 1;
		for (inner = 2; inner < outer; inner++)
		{
			if (outer % inner == 0)
			{
				flag = 0;
				break;
			}
		}
		if (flag == 1)
		{
			printf("%d\n", outer);
		}
	}
	printf("Completed\n");
}
 
int main()
{
	printPrime(10);
	return 0;
}

可以看出,对于计算素数这个程序,使用循环使用跳转标签,可以省去如C语言 flag 这样的判断

02

Golang IP 地址字符串整数/string int 相互转换

概览

Go 中没有 C 语言 inet_atoninet_ntoa 类似的转换 IP 函数,

所以需要手动封装两个函数

(转换的方法有多种,我选择了简洁的)

实现

代码语言:javascript
复制
package main

import (
    "fmt"
    "math/big"
    "net"
)

func InetNtoA(ip int64) string {
    return fmt.Sprintf("%d.%d.%d.%d",
        byte(ip>>24), byte(ip>>16), byte(ip>>8), byte(ip))
}

func InetAtoN(ip string) int64 {
    ret := big.NewInt(0)
    ret.SetBytes(net.ParseIP(ip).To4())
    return ret.Int64()
}

func main() {
    ip := "192.168.78.123"
    ipInt := InetAtoN(ip)

    fmt.Printf("convert string ip [%s] to int: %d\n", ip, ipInt)
    fmt.Printf("convert int ip [%d] to string: %s\n", ipInt, InetNtoA(ipInt))
}

注:InetAtoN 最好加安全验证,检查 IP 字符串的有效性, 可以判断 net.ParseIP(ip).To4() 是否为 nil

运行效果

可以使用 ping 命令简单验证一下转换的结果

03

Golang 八进制 utf-8 编码转中文

概览

当调试程序,打印出变量的值时,有可能输出的是八进制 utf-8 编码(尤其是 protobuf 变量)

例如:\346\200\241\346\200\241\346\200

这样的字符串如果作为字面量,go 可以自动转化,

但如果是从文件或 string 中读取,就不行了。

可以使用正则表达式简单处理下

代码示例

代码语言:javascript
复制
package main

import (
    "fmt"
    "regexp"
    "strconv"
)

// 转换8进制utf-8字符串到中文
// eg: `\346\200\241` -> 怡
func convertOctonaryUtf8(in string) string {
    s := []byte(in)
    reg := regexp.MustCompile(`\\[0-7]{3}`)

    out := reg.ReplaceAllFunc(s,
        func(b []byte) []byte {
            i, _ := strconv.ParseInt(string(b[1:]), 8, 0)
            return []byte{byte(i)}
        })
    return string(out)
}

func main() {
    s1 := "\346\200\241" // 字面量
    s2 := `\346\200\241` // 原始字符串

    fmt.Println("s1 =", s1)
    fmt.Println("s2 =", s2)

    // 转化 s2
    s3 := convertOctonaryUtf8(s2)
    fmt.Println("s3 =", s3)
}

运行结果

04

Golang httputil 库,一行代码搞定 http 请求

概览

在 golang 程序中进行 http 请求时,一般的步骤是:

  • 组合 url 和 param 参数
  • get 和 put 需要准备请求体数据
  • 进行 http 请求(设置超时)
  • 错误判断和状态码判断
  • http 返回内容解析

如果后端程序每个 http 请求都如上面这样处理,将产生很多相似的代码,

并且在复制代码的时候,容易出错(需要修改的地方忘记修改),浪费 debug 的时间。

于是,我封装了一个简便的 httputil 库,用于 http 请求。

详见 https://github.com/chinaran/httputil

  • 支持 get, post, put, patch, delete 方法
  • 支持 string, []byte, map, struct 作为 request 和 response 数据
  • 默认超时:30s
  • 默认传输类型:application/json

示例

代码语言:javascript
复制
package main

import (
	"context"
	"log"

	hu "github.com/chinaran/httputil"
)

func main() {
	// get
	urlGet := "https://httpbin.org/get?hello=world"
	respGetM := map[string]interface{}{}
	if err := hu.Get(context.TODO(), urlGet, &respGetM, hu.WithLogTimeCost()); err != nil {
		log.Printf("Get %s err: %s", urlGet, err)
		return
	}
	log.Printf("Get %s map response: %+v", urlGet, respGetM)
	respGetStr := ""
	if err := hu.Get(context.TODO(), urlGet, &respGetStr, hu.WithLogTimeCost()); err != nil {
		log.Printf("Get %s err: %s", urlGet, err)
		return
	}
	log.Printf("Get %s string response: %+v", urlGet, respGetStr)

	// post
	urlPost := "https://httpbin.org/post"
	req := map[string]string{"hello": "world"}
	respPost := struct {
		Data string `json:"data"`
	}{}
	if err := hu.Post(context.TODO(), urlPost, &req, &respPost, hu.WithLogTimeCost()); err != nil {
		log.Printf("Post %s err: %s", urlPost, err)
		return
	}
	log.Printf("Post %s struct response: %+v", urlPost, respPost)
}

示例结果

05

Golang debuglog 库,调试程序时快捷查看变量值

概览

在调试 golang 程序时,加断点查看变量值固然是一种方法,但更多的时候只是简单的加个 log 看一下。

可以 fmt.Printf("%+v", xxx), 如果想查看 json 还要转换,很麻烦。

于是,我封装了一个简便的 debuglog 库,用于 debug 变量。

详见 https://github.com/chinaran/debuglog

  • debuglog.Val(): 打印变量
  • debuglog.SpewVal(): 使用 spew 库打印变量(可以详细看到结构体每个字段的定义和值)
  • debuglog.ToJson(): 转成 json 字符串打印
  • debuglog.ToJsonPretty(): 有缩进和换行的 json 字符串

调试好程序解决 bug 后,删掉所有的 debuglog 即可。

示例

代码语言:javascript
复制
package main

import "github.com/chinaran/debuglog"

type TestJson struct {
	Id   int64
	Name string
}

func main() {
	intVal := 123
	debuglog.Val(intVal)
	debuglog.Val(intVal, "prefix1")
	debuglog.Val(intVal, "prefix1", "prefix2")

	testJson := TestJson{Id: 987, Name: "alan"}

	debuglog.SpewVal(testJson, "testJson Spew")
	// debuglog.OctUtf8Val(testJson, "testJson")

	debuglog.ToJson(testJson, "testJson")
	debuglog.ToJsonPretty(testJson, "testJson Pretty")
}

示例结果

06

go-httpbin, http 请求测试工具推荐

httpbin 是什么

A simple HTTP Request & Response Service (written in Python + Flask).

一个简单的 HTTP 请求和回复测试服务。

详见: https://httpbin.org/

httpbin 用途

http 开发调试

httpbin 提供了 GET/PUT/POST/PATCH/DELETET 常见方法,可以把请求头、参数等返回,类似 Echo 服务。方便调试 http 请求。

http 库测试

使用开源或者自己项目封装的 http 请求库,可以把 httpbin 作为服务端,测试各种场景。

除了在线的 https://httpbin.org/,也可以本地部署。

云原生示例服务

可作为演示服务,测试平台功能。例如,isito 就有 httpbin sample 服务,用来实验 istio 各种特性

详见: https://github.com/istio/istio/tree/master/samples/httpbin

httpbin 常用接口

/get 接口

/put, /post, /patch 还会打印出请求体数据

代码语言:javascript
复制
curl 'https://httpbin.org/get?paramA=aa'
{
  "args": {
    "paramA": "aa"
  },
  "headers": {
    "Accept": "*/*",
    "Host": "httpbin.org",
    "User-Agent": "curl/7.64.1",
    "X-Amzn-Trace-Id": "Root=1-6107dcac-1d6d3fb32f67d8184c184992"
  },
  "origin": "111.207.117.50",
  "url": "https://httpbin.org/get?paramA=aa"
}

/status/{codes} 接口

用来返回特定的状态码

代码语言:javascript
复制
curl 'https://httpbin.org/status/418'

    -=[ teapot ]=-

       _...._
     .'  _ _ `.
    | ."` ^ `". _,
    \_;`"---"`|//
      |       ;/
      \_     _/
        `"""`

/ip 接口

返回原始 ip

代码语言:javascript
复制
curl 'https://httpbin.org/ip'
{
  "origin": "xxx.xxx.xxx.xxx"
}

/delay/{delay} 接口

延时一定时间返回

还有很多测试接口,可在官网查看

go-httpbin 优化

httpbin 的 github https://github.com/postmanlabs/httpbin 在 2018.11 后就没有更新了,有一些需求和 bug 都没有解决。

无意将发现了 go-httpbin, 是一个只使用 golang 标准库实现的 httpbin。

所以我 fork 了 mccutchen/go-httpbin 项目,并添加了一些特性。

  • add -response-delay args (more observability, except /delay/{time} api)
  • pretty response json (more like httpbin)
  • add query param envs (identify httpbin instance, default show HOSTNAME for k8s. eg: curl http://localhost:8080/get?envs=ENV1,ENV2)
  • add anything api (show anything request and response)

详见: https://github.com/chinaran/go-httpbin

可以直接使用 docker 尝试运行

代码语言:javascript
复制
docker run -p 8080:80 ghcr.io/chinaran/go-httpbin:1.2-alpine3.13

示例:(请求注入了 sidecar 的 httpbin 服务)

代码语言:javascript
复制
kubectl -n ran-test exec -it client-54d574b9b-6w9xc -- curl http://go-httpbin/get
{
    "envs": {
        "HOSTNAME": "go-httpbin-6f55bbcfcd-skrxl"
    },
    "args": {},
    "headers": {
        "Accept": "*/*",
        "Content-Length": "0",
        "Host": "go-httpbin",
        "User-Agent": "curl/7.76.1",
        "X-B3-Parentspanid": "d4ae8aad7301da2d",
        "X-B3-Sampled": "1",
        "X-B3-Spanid": "68b5055ffd105f5b",
        "X-B3-Traceid": "26e3ee5a3196b1bcd4ae8aad7301da2d",
        "X-Client-Name": "client",
        "X-Client-Namespace": "ran-test",
        "X-Envoy-Attempt-Count": "1",
        "X-Forwarded-Client-Cert": "By=spiffe://cluster.local/ns/ran-test/sa/default;Hash=0cb9c538a64d9f747c86731252bd28d6e9121c7cf0be731f2484fd3b4a1af57f;Subject=\"\";URI=spiffe://cluster.local/ns/ran-test/sa/default",
        "X-Forwarded-Proto": "http",
        "X-Request-Id": "1f2a3700-1bdf-9a0a-9091-2c6aba324606"
    },
    "origin": "127.0.0.1:46756",
    "url": "http://go-httpbin/get"
}
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-08-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 云原生技术社区 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 概览
  • 实现
  • 运行效果
  • 概览
  • 代码示例
  • 运行结果
  • 概览
  • 示例
  • 示例结果
  • 概览
  • 示例
  • 示例结果
  • httpbin 是什么
  • httpbin 用途
  • httpbin 常用接口
  • go-httpbin 优化
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档