在Coding的时候,难免会有一些重复的代码或者形式相似的代码,在写这些代码的时候,你会觉得索然无味,甚至有点讨厌。这时候,你就会想,这段代码是否可以抽象成一个通用的片段,我简单敲几个快捷键就出来了呢。这也就代码片段所解决的问题。

现在几乎大部分的编译器都支持代码片段,如下图就是我用VSCode写一段简单的代码。

在写这段代码的时候我就用到了代码片段,即1中,当我们敲下func关键词后出现的第三个提示。只需要Tab一下,我们就可以使用该片段。如2中所示,该片段已经为我设定好了哪些位置可能需要填写,我们只需要Tab到对应位置填写即可。

其实这样的片段,我们一直在使用,如for自动补全格式,switch自动补全case等,当然这些都是他人已经定制好的,有时我们需要自己去定义一些符合自己业务场景的该怎么做呢?

VSCode 自定义Go片段

如下图所示:

  1. Shift + Cmd + P 打开命令窗口,输入snippets;

  2. 选择 Preferences: Open User Snippets;

  3. 选择 go.json

这样我们就可以编辑该go.json文件了。片段的书写就是以json的形式在该文件内定义的,具体格式如下:

"Print to console": {
	"prefix": "log",
	"body": [
		"console.log('$1');",
		"$2"
	],
	"description": "Log output to console"
},

其中:

  1. prefix 指的是前缀,也就是当我们敲出log时,就自动提示该片段;
  2. body 就是片段的具体内容,$1,$2… 是占位符号,当使用片段时就可以使用Tab在这些占位符之间跳跃;我们也可以使用${1:default}来设置一些标签帮助我们辨识。
  3. description 以及 Print to console 都是我们在选择该片段时提示的内容。description可不写。

效果如下所示:

例子

1.在使用gin的时候,我们的Handle函数总是这样的func HandleXXX(c *gin.Context),于是我们可以定义一个gin handle的片段;

	"GIN Route Handler": {
		"prefix": "ginh",
		"body": [
			"// Handle${1} godoc",
			"func Handle${1}(c *gin.Context) {",
			"$2",
			"}",
		]
	},

2.在使用gorm的时候,我们定义结构需要指定字段名称等,其形式总是这样的gorm:\"column:xxx",于是:

	"GORM" : {
		"prefix": "gormcl",
		"body" : [
			"`gorm:\"column:${1:columnName}\"`",
			"$2"
		]
	},

3.在使用Swago自动生成API文档时,我们需要去按照固定的范式写注释,于是:

	"SWAG API": {
		"prefix": "swag",
		"body": [
			"// @Summary $1",
                        "// @Tags $2",
			"// @Description $3",
			"// @Accept ${4:mpfd} ${5:json}",
			"// @Produce ${6:json}",
			"// @Param ${7:param} ${8:query} ${9:string} ${10:true} \"${11:describe}\"  ${12:Enums()} ${13:default}",
			"// @Success 200 {${14:object}} ${15:model}",
			"// @Router /${16:path} [${17:get}]"
		]
	},

等等,有了片段后,我们可以通过prefix+Tab更加高效的将这些重复内容编写出来,快去试试吧~

vim自定义Go片段

当然,除了宇宙第一编辑器VSCode外,vim上使用片段也是相当爽快的。

在vim上使用片段,需要装两个插件

  Plugin 'SirVer/ultisnips'
  Plugin 'honza/vim-snippets'

前者是片段的引擎,后者是网友提供的一些片段集合,安装好这两个插件后,我们在~/.vim/bundle/vim-snippets/UltiSnips~/.vim/bundle/vim-snippets/snippets 下能看到多种语言的代码片段。

这里 UltiSnips/*snippets/* 下的区别是片段使用的引擎不一样。 SnipMateUltiSnips是vim比较流行的片段引擎。 不同的引擎,语法稍有区别。 但UltiSnips是兼容SnipMate的。

我们这里主要看到~/.vim/bundle/vim-snippets/UltiSnips/go.snippets。打开该文件,我们能看到很多已经定义好的片段,只要按照该语法在该文件加入自定义片段即可使用。

其语法结构很简单

snippet <prefix> <name>
<body>
endsnippet

有时我们会看到<name> 后面会接着b,a,等字符。

其中b意味着 begin (snippet should be expanded only at the beginning of a line),也就是表示该片段只能在一段开始的时候使用。

a代表这自动展开的意思,其实还有w,i,r,s,t,m等限定词,具体可以使用:help ultisnip查看帮助文档。

了解语法后,可以将上面VSCode使用的片段在vim实现了~

例子

1.gin handle

snippet ginh "GIN Route Handler" b
// Handle$1 godoc
func Handle$1(c *gin.Context) {
    $2
}
endsnippet

2.gorm

snippet gormcl "gorm comments" 
\`gorm:"column:${1:columnName}$2"\`
endsnippet

3.swago

snippet swag "swag comments for api doc" b
// @Summary $1
// @Tags $2
// @Description $3
// @Accept ${4:mpfd} ${5:json}
// @Produce ${6:json}
// @Param ${7:param} ${8:query} ${9:string} ${10:true} "${11:describe}" ${12:Enums()} ${13:default}
// @Success 200 {${14:object}} ${15:model}
// @Router ${16:path} [${17:get}]
endsnippet

在实际的coding过程中,不断的积累一些代码片段,写一些适合自己业务场景的片段,确实能行而有效的提高代码的效率,提高代码的整洁度。