快速上手golang(持续更新)

news2024/11/8 8:39:58

由于项目需要,我不得不快速掌握go语言来帮助我进行项目的开发。时间紧迫到我来不及去了解语言的特性就直接项目上手了。我决定就先熟悉一个主流的go框架和go语言的一些日常用法,之后就得滑着这只破船摇摇晃晃上路了。

1 基础命令

就说几个用的多的,配环境就不说了,我就说说我的理解,可能很不专业:

go init mod [example] # 初始化一个go包
go get [package] # 拉取一个go模块,类似python的pip install
go mod tidy # 模块对齐,快速拉取所有需要的模块

我感觉有了这三个命令就可以勉勉强强上路了哈哈哈哈[狗头]。

2 gin框架

直接代码上手了,不管他里面做了什么。这是一个golang很常用的基础框架。

2.1 启动http服务

package main

import (
	"net/http"

	"github.com/gin-gonic/gin"
)

func main() {
	r := gin.Default()
	r.GET("/ping", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{
			"message": "pong",
		})
	})

	r.Run()
}

2.2 RESTFUL API

RESTful API是利用HTTP请求访问或使用数据的应用程序接口(API)的体系结构样式。它基于表示性状态转移(REST)的原则,是一种Web服务开发中经常使用的体系结构样式和通信方式。RESTful API的主要特点包括:

  1. 资源(Resources):以URL的形式表示应用程序中的资源,如/users表示用户资源。
  2. 统一接口(Uniform Interface):使用HTTP方法(GET、POST、PUT、DELETE)对资源进行操作,并使用HTTP状态码和响应内容来表示操作的结果。
  3. 无状态(Stateless):每个请求都是独立的,服务器不会在请求之间保留任何状态信息。
  4. 可缓存(Cacheable):对于不经常变化的资源,可以启用缓存提高性能。
  5. 分层系统(Layered System):可以通过代理服务器等中间件实现系统的扩展性和安全性。

RESTful API的优点包括:

  1. 轻量级:使用HTTP协议进行通信,使用简单的数据格式进行数据交换。
  2. 易于扩展:使用标准的HTTP方法和数据格式,可以很容易地扩展和修改API。
  3. 易于缓存:使用标准的HTTP协议,可以使用缓存技术来提高性能和可扩展性。
  4. 易于测试:通过浏览器或其他工具可以访问和测试API。

RESTful API在多个领域有广泛应用,包括电商领域的商品展示、购物车管理、订单处理等;社交网络领域的用户管理、好友关系及消息推送等功能;物联网领域的设备管理、数据采集和远程控制;以及移动应用的数据同步、用户认证和推送消息等功能。

总的来说,RESTful API为Web服务和应用程序提供了一种高效、可扩展且易于理解的通信方式,是构建现代化Web应用的重要组成部分。

2.2.1 Method
func main() {
	r := gin.Default()

	r.GET("/someGet", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{
			"message": "get",
		})
	})

	r.POST("/somePost", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{
			"message": "post",
		})
	})

	r.PUT("/somePut", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{
			"message": "put",
		})
	})

	r.DELETE("/someDelete", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{
			"message": "delete",
		})
	})

	r.PATCH("/somePatch", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{
			"message": "patch",
		})
	})

	r.HEAD("/someHead", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{
			"message": "head",
		})
	})

	r.OPTIONS("/someOpt", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{
			"message": "options",
		})
	})

	r.Run(":3000")
}

2.3 参数传递和获取

2.3.1 路径携带参数
func main() {
	router := gin.Default()

	router.GET("/user/:name", func(ctx *gin.Context) {
		name := ctx.Param("name")
		ctx.String(http.StatusOK, "Hello %s", name)
	})

	router.GET("/user/:name/*action", func(ctx *gin.Context) {
		name := ctx.Param("name")
		action := ctx.Param("action")
		message := name + "is" + action
		ctx.String(http.StatusOK, "Hello %s", message)
	})

	router.POST("/user/:name/*action", func(ctx *gin.Context) {
		b := ctx.FullPath() == "/user/:name/*action"
		ctx.String(http.StatusOK, "%t", b)
	})

	router.GET("user/groups", func(ctx *gin.Context) {
		ctx.String(http.StatusOK, "The acailable groups are [...]")
	})

	router.Run(":3000")
}

2.3.2 Querystring参数
func main() {
	router := gin.Default()
	router.GET("/welcome", func(ctx *gin.Context) {
		firstname := ctx.DefaultQuery("firstname", "Guest")
		lastname := ctx.Query("lastname")
		ctx.Request.URL.Query().Get("lastname")
		ctx.String(http.StatusOK, "Hello %s %s", firstname, lastname)
	})

	router.Run(":3000")
}

2.3.3 Form表单
func main() {
	router := gin.Default()
	router.POST("/form_post", func(ctx *gin.Context) {
		message := ctx.PostForm("message")
		lenn := ctx.DefaultPostForm("lenn", "anonymous")

		ctx.JSON(http.StatusOK, gin.H{
			"status":  "posted",
			"message": message,
			"lenn":    lenn,
		})
	})

	router.Run(":3000")
}
2.3.4 文件上传
func main() {
	router := gin.Default()
	router.MaxMultipartMemory = 8 << 20
	router.POST("/upload", func(ctx *gin.Context) {
		file, _ := ctx.FormFile("file")
		log.Println(file.Filename)
		ctx.SaveUploadedFile(file, "/home/lennlouis/")
		ctx.String(http.StatusOK, fmt.Sprintf("'%s' upload!", file.Filename))
	})

	router.Run(":3000")
}
2.3.4.1 单文件上传
func main() {
	router := gin.Default()
	router.MaxMultipartMemory = 8 << 20
	router.POST("/upload", func(ctx *gin.Context) {
		file, _ := ctx.FormFile("file")
		log.Println(file.Filename)
		ctx.SaveUploadedFile(file, "/home/lennlouis/")
		ctx.String(http.StatusOK, fmt.Sprint("'%s' upload!", file.Filename))
	})
	router.Run(":8000")

}

2.3.4.2 多文件上传
func main() {
	router := gin.Default()
	router.MaxMultipartMemory = 8 << 20
	router.POST("/upload", func(ctx *gin.Context) {
		form, _ := ctx.MultipartForm()
		files := form.File["upload[]"]

		for _, file := range files {
			log.Println(file.Filename)
			ctx.SaveUploadedFile(file, "/home/lennlouis/")
		}
		ctx.String(http.StatusOK, fmt.Sprintf("%d files uploaded!", len(files)))
	})
	router.Run(":8000")
}

2.4 路由(路由分组)

func loginEndpoint(c *gin.Context) {
	fmt.Println(c.Request.URL)
}

func submitEndpoint(c *gin.Context) {
	fmt.Println(c.Request.URL)
}

func readEndpoint(c *gin.Context) {
	fmt.Println(c.Request.URL)
}

func main() {
	router := gin.Default()
	v1 := router.Group("/v1")
	{
		v1.POST("/login", loginEndpoint)
		v1.POST("/submit", submitEndpoint)
		v1.POST("/read", readEndpoint)
	}

	v2 := router.Group("/v2")
	{
		v2.POST("/login", loginEndpoint)
		v2.POST("/submit", submitEndpoint)
		v2.POST("/read", readEndpoint)
	}

	router.Run(":8000")
}

2.5 中间件

2.5.1 中间件的使用

2.5.2 自定义recover中间件

2.6 日志

2.6.1 写入到文件
func main() {
	gin.DisableConsoleColor()
	f, _ := os.Create("gin.log")
	gin.DefaultWriter = io.MultiWriter(f)
	router := gin.Default()
	router.GET("/ping", func(ctx *gin.Context) {
		ctx.String(http.StatusOK, "pong")
	})

	router.Run(":8000")
}
2.6.2 自定义格式
func main() {
	router := gin.New()
	router.Use(gin.LoggerWithFormatter(func(param gin.LogFormatterParams) string { // your custom format
		return fmt.Sprintf("%s - [%s] \"%s %s %s %d %s \"%s\" %s\"\n",
			param.ClientIP,
			param.TimeStamp.Format(time.RFC1123),
			param.Method,
			param.Path,
			param.Request.Proto,
			param.StatusCode,
			param.Latency,
			param.Request.UserAgent(),
			param.ErrorMessage,
		)
	}))
	router.Use(gin.Recovery())
	router.GET("/ping", func(c *gin.Context) {
		c.String(http.StatusOK, "pong")
	})
	router.Run(":8080")
}

2.7 模型绑定和验证

2.7.1 JSON
2.7.2 Query String
type Person struct {
	Name    string `form:"name`
	Address string `form:"address"`
}

func main() {
	router := gin.Default()
	router.Any("/testing", startPage)
	router.Run(":8000")
}

func startPage(c *gin.Context) {
	var person Person
	if c.ShouldBindQuery(&person) == nil {
		log.Println("====== Only Bind By Query String ======")
		log.Println(person.Name)
		log.Println(person.Address)
	}

	c.String(http.StatusOK, "Success")
}
2.7.3 QueryString or PostData
2.7.4 Bind Url
2.7.5 Bind Header

2.8 Protobuf

  1. 安装编译器

    go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
    
  2. 生成代码

    protoc -I=$SRC_DIR --go_opt=paths=source_relative --go_out=$DST_DIR $SRC_DIR/helloworld.proto
    

grpc

持续更新

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1861771.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

QT拖放事件之八:通过全局剪切板中的接口QClipboard::mimeData()来获取MIME类型数据

1、演示效果 首先向剪切板写入数据,然后点击paste按钮进行从全局剪切板中 获取 MIME数据。。。 2、核心代码 void Widget::on_pasteBtn_clicked() {const QClipboard* clipBoard = QGuiApplication::clipboard()

理解和处理不同类型的上下文的新型的语言模型ReALM

在人类的日常交流中&#xff0c;模糊的代词如“他们”或“那个”常常出现&#xff0c;它们的意义通常依赖于上下文才能明确。这种上下文的理解对于对话助手来说至关重要&#xff0c;因为它们旨在提供一种自然的交流体验。然而&#xff0c;现有的对话助手在处理这类模糊引用时往…

Java HashMap 简介

HashMap 简介 HashMap 主要用来存放键值对&#xff0c;它基于哈希表的 Map 接口实现&#xff0c;是常用的 Java 集合之一&#xff0c;是线程不安全的。 HashMap&#xff1b;可以存储 null 的 key 和 value &#xff0c;但 null 作为 key 只能有一个&#xff0c;null 作为值可以…

非强化学习的对齐方法

在文章《LLM对齐“3H原则”》和《深入理解RLHF技术》中&#xff0c;我们介绍了大语言模型与人类对齐的“3H原则”&#xff0c;以及基于人类反馈的强化学习方法&#xff08;RLHF&#xff09;&#xff0c;本文将继续介绍另外一种非强化学习的对齐方法&#xff1a;直接偏好优化&am…

深度学习语义分割算法之基础知识

文章目录 前言一、图像分割介绍1.语义分割2.实例分割3.全景分割 二、常见数据集格式1.PASCAL VOC2.MS COCO 三、语义分割结果四、语义分割常见评价指标1.Pixel Accuracy2.mean Accuracy3.mean IoU 五、语义分割标注工具结束语 &#x1f482; 个人主页:风间琉璃&#x1f91f; 版…

FireFox 编译指南2024 Windows10篇-环境准备(一)

1. 引言 在开源浏览器项目中&#xff0c;Firefox因其高性能和灵活性而备受开发者青睐。为了在本地环境中编译和定制Firefox&#xff0c;开发者需要做好充分的环境准备工作。这不仅是编译成功的基础&#xff0c;也是后续调试、优化和二次开发的关键步骤。 编译Firefox是一个复…

硬核实力再亮,玩出梦想科技发布全球首款安卓系统空间计算机

6月25日&#xff0c;玩出梦想科技在新加坡召开全球新品发布会&#xff0c;正式发布全球首款安卓系统空间计算机——玩出梦想MR&#xff0c;填补了空间计算机在安卓生态的空白。 作为品牌沉淀两年的破晓之作&#xff0c;玩出梦想MR以业内领先软硬件配置&#xff0c;强大自研算法…

kafka--发布-订阅消息系统

1. Kafka概述 1. kafka是什么 kafka是分布式的、高并发的、基于发布/订阅模式的消息队列软件系统。 kafka中的重要组件 Producer&#xff1a;消息生产者&#xff0c;发布消息到Kafka集群的终端或服务Consume&#xff1a;消费者&#xff0c;从Kafka集群中消费消息的终端或服…

CAN报文的发送类型-OnChange、OnWrite、IfActive、Repetition

CAN报文的发送类型分为基本发送类型和混合发送类型两大类 CAN基本发送类型包括Cyclic周期发送、OnChange变化时发送、OnWrite写入时发送和IfActive有效时发送。基本发送类型中的Cyclic称为周期型,而其他3个类型称为事件型(Event)。发送次数是通过定义Repetition重复次数来实…

AI 编程探索- iOS动态标签控件

需求分析&#xff1a; 标签根据文字长度&#xff0c;自适应标签居中显示扩展 超过内容显示范围&#xff0c;需要换行显示&#xff0c;且保持居中显示 AI实现过程 提问&#xff1a; 回答&#xff1a; import UIKit import SnapKitclass DynamicLabelsContainerView: UIView…

python基础篇(5):None类型

1 None类型 Python中有一个特殊的字面量&#xff1a;None&#xff0c;其类型是&#xff1a;<class NoneType> 无返回值的函数&#xff0c;实际上就是返回了&#xff1a;None这个字面量 None表示&#xff1a;空的、无实际意义的意思 函数返回的None&#xff0c;就表示…

[MYSQL] MYSQL库的操作

前言 本文主要介绍MYSQL里 库 的操作 请注意 : 在MYSQL中,命令行是不区分大小写的 1.创建库 create database [if not exists] database_name [charsetutf8 collateutf8_general_ci] ...] create database 是命名语法,不可省略[if not exists] 如果不存在创建,如果存在跳过…

基于CRITIC-TOPSIS法的各地区评价

1.CRITIC-TOPSIS法原理 1.1 基本理论 CRITIC-TOPSIS法是一种结合CRITIC&#xff08;Criteria Importance Through Intercriteria Correlation&#xff09;法和TOPSIS&#xff08;Technique for Order Preference by Similarity to Ideal Solution&#xff09;法的综合评价方法…

盲盒小程序开发:解锁未知,探索无限惊喜

一、开启新篇章 在追求独特与新颖的时代&#xff0c;盲盒以其神秘感与未知性&#xff0c;成为了年轻人热衷的购物新方式。为了满足这一市场需求&#xff0c;我们精心打造了一款全新的盲盒小程序&#xff0c;带您步入一个充满未知与惊喜的购物新领域。 二、产品亮点 精选商品&…

B端系统:日历组件设计,小组件蕴含大学问。

B端日历组件在企业级应用中具有重要作用&#xff0c;它可以用于管理和展示企业内部的日程安排、会议安排、任务分配等。 设计B端日历组件时&#xff0c;可以考虑以下几点&#xff1a; 显示方式&#xff1a;提供多种显示方式&#xff0c;例如月视图、周视图、日视图等&#xf…

FineReport聚合报表与操作

一、报表类型 模板设计是 FineReport 学习过程中的主要难题所在&#xff0c;FineReport 模板设计主要包括普通报表、聚合报表、决策报表三种设计类型。 报表类型简介- FineReport帮助文档 - 全面的报表使用教程和学习资料 二、聚合报表 2-1 介绍 聚合报表指一个报表中包含多个…

解决了!暗影精灵8 Pro酷睿版无声音,扬声器和麦克风都没有声音!

困扰好几天的问题解决了&#xff01; 暗影精灵8 Pro酷睿版无声音&#xff0c;扬声器和麦克风都没有声音&#xff01;&#xff01;方法适用于OMEN by HP Gaming Laptop 16-k0xxx&#xff08;暗影精灵8 Pro酷睿版&#xff09;的Windows 10声卡驱动&#xff01; 朋友们&#xff…

启动VMWare虚拟机报错

1. 无法打开内核设备“\\.\VMCIDev\VMX”: 操作成功完成。是否在安装 VMware Workstation 后重新引导? 模块“DevicePowerOn”启动失败。 未能启动虚拟机。 解决办法: 解决办法: 将 Ubuntu 64 位.vmx 找到vmci0.present"TRUE"这行改成 vmci0.present "FAL…

pinia.js报patchToApply.hasOwnProperty is not a function

vue3 ts pinia.js 先看报错> patchToApply.hasOwnProperty is not a function 错误信息&#xff1a; pinia.js?v91704efd:913 Uncaught (in promise) TypeError: patchToApply.hasOwnProperty is not a functionat mergeReactiveObjects (pinia.js?v91704efd:913:23)…