Go语言单元测试基础从入门到放弃

目录
  • Go语言测试
    • go test工具
  • 单元测试函数
    • 格式
    • 单元测试示例
    • go test -v
    • go test -run
  • 回归测试
    • 跳过某些测试用例
    • 子测试
  • 表格驱动测试
    • 介绍
    • 示例
    • 并行测试
    • 使用工具生成测试代码
  • 测试覆盖率
  • testify/assert
    • 安装
    • 使用示例
  • 总结

Go语言测试

这是Go单测从入门到放弃系列教程的第0篇,主要讲解在Go语言中如何做单元测试以及介绍了表格驱动测试、回归测试,并且介绍了常用的断言工具。

go test工具

Go语言中的测试依赖go test命令。编写测试代码和编写普通的Go代码过程是类似的,并不需要学习新的语法、规则或工具。

go test命令是一个按照一定约定和组织的测试代码的驱动程序。在包目录内,所有以_test.go为后缀名的源代码文件都是go test测试的一部分,不会被go build编译到最终的可执行文件中。

*_test.go文件中有三种类型的函数,单元测试函数、基准测试函数和示例函数。

类型 格式 作用
测试函数 函数名前缀为Test 测试程序的一些逻辑行为是否正确
基准函数 函数名前缀为Benchmark 测试函数的性能
示例函数 函数名前缀为Example 为文档提供示例文档

go test命令会遍历所有的*_test.go文件中符合上述命名规则的函数,然后生成一个临时的main包用于调用相应的测试函数,然后构建并运行、报告测试结果,最后清理测试中生成的临时文件。

单元测试函数

格式

每个测试函数必须导入testing包,测试函数的基本格式(签名)如下:

func TestName(t *testing.T){
    // ...
}

测试函数的名字必须以Test开头,可选的后缀名必须以大写字母开头,举几个例子:

func TestAdd(t *testing.T){ ... }
func TestSum(t *testing.T){ ... }
func TestLog(t *testing.T){ ... }

其中参数t用于报告测试失败和附加的日志信息。testing.T的拥有的方法如下:

func (c *T) Cleanup(func())
func (c *T) Error(args ...interface{})
func (c *T) Errorf(format string, args ...interface{})
func (c *T) Fail()
func (c *T) FailNow()
func (c *T) Failed() bool
func (c *T) Fatal(args ...interface{})
func (c *T) Fatalf(format string, args ...interface{})
func (c *T) Helper()
func (c *T) Log(args ...interface{})
func (c *T) Logf(format string, args ...interface{})
func (c *T) Name() string
func (c *T) Skip(args ...interface{})
func (c *T) SkipNow()
func (c *T) Skipf(format string, args ...interface{})
func (c *T) Skipped() bool
func (c *T) TempDir() string

单元测试示例

就像细胞是构成我们身体的基本单位,一个软件程序也是由很多单元组件构成的。单元组件可以是函数、结构体、方法和最终用户可能依赖的任意东西。总之我们需要确保这些组件是能够正常运行的。单元测试是一些利用各种方法测试单元组件的程序,它会将结果与预期输出进行比较。

接下来,我们在base_demo包中定义了一个Split函数,具体实现如下:

// base_demo/split.go
package base_demo
import "strings"
// Split 把字符串s按照给定的分隔符sep进行分割返回字符串切片
func Split(s, sep string) (result []string) {
 i := strings.Index(s, sep)
 for i > -1 {
  result = append(result, s[:i])
  s = s[i+1:]
  i = strings.Index(s, sep)
 }
 result = append(result, s)
 return
}

在当前目录下,我们创建一个split_test.go的测试文件,并定义一个测试函数如下:

// split/split_test.go
package split
import (
 "reflect"
 "testing"
)
func TestSplit(t *testing.T) { // 测试函数名必须以Test开头,必须接收一个*testing.T类型参数
 got := Split("a:b:c", ":")         // 程序输出的结果
 want := []string{"a", "b", "c"}    // 期望的结果
 if !reflect.DeepEqual(want, got) { // 因为slice不能比较直接,借助反射包中的方法比较
  t.Errorf("expected:%v, got:%v", want, got) // 测试失败输出错误提示
 }
}

此时split这个包中的文件如下:

❯ ls -l
total 16
-rw-r--r--  1 liwenzhou  staff  408  4 29 15:50 split.go
-rw-r--r--  1 liwenzhou  staff  466  4 29 16:04 split_test.go

在当前路径下执行go test命令,可以看到输出结果如下:

❯ go test
PASS
ok      golang-unit-test-demo/base_demo       0.005s

go test -v

一个测试用例有点单薄,我们再编写一个测试使用多个字符切割字符串的例子,在split_test.go中添加如下测试函数:

func TestSplitWithComplexSep(t *testing.T) {
 got := Split("abcd", "bc")
 want := []string{"a", "d"}
 if !reflect.DeepEqual(want, got) {
  t.Errorf("expected:%v, got:%v", want, got)
 }
}

现在我们有多个测试用例了,为了能更好的在输出结果中看到每个测试用例的执行情况,我们可以为go test命令添加-v参数,让它输出完整的测试结果。

❯ go test -v
=== RUN   TestSplit
--- PASS: TestSplit (0.00s)
=== RUN   TestSplitWithComplexSep
    split_test.go:20: expected:[a d], got:[a cd]
--- FAIL: TestSplitWithComplexSep (0.00s)
FAIL
exit status 1
FAIL    golang-unit-test-demo/base_demo 0.009s

从上面的输出结果我们能清楚的看到是TestSplitWithComplexSep这个测试用例没有测试通过。

go test -run

单元测试的结果表明split函数的实现并不可靠,没有考虑到传入的sep参数是多个字符的情况,下面我们来修复下这个Bug:

package base_demo
import "strings"
// Split 把字符串s按照给定的分隔符sep进行分割返回字符串切片
func Split(s, sep string) (result []string) {
 i := strings.Index(s, sep)
 for i > -1 {
  result = append(result, s[:i])
  s = s[i+len(sep):] // 这里使用len(sep)获取sep的长度
  i = strings.Index(s, sep)
 }
 result = append(result, s)
 return
}

在执行go test命令的时候可以添加-run参数,它对应一个正则表达式,只有函数名匹配上的测试函数才会被go test命令执行。

例如通过给go test添加-run=Sep参数来告诉它本次测试只运行TestSplitWithComplexSep这个测试用例:

❯ go test -run=Sep -v
=== RUN   TestSplitWithComplexSep
--- PASS: TestSplitWithComplexSep (0.00s)
PASS
ok      golang-unit-test-demo/base_demo 0.010s

最终的测试结果表情我们成功修复了之前的Bug。

回归测试

我们修改了代码之后仅仅执行那些失败的测试用例或新引入的测试用例是错误且危险的,正确的做法应该是完整运行所有的测试用例,保证不会因为修改代码而引入新的问题。

❯ go test -v
=== RUN   TestSplit
--- PASS: TestSplit (0.00s)
=== RUN   TestSplitWithComplexSep
--- PASS: TestSplitWithComplexSep (0.00s)
PASS
ok      golang-unit-test-demo/base_demo 0.011s

测试结果表明我们的单元测试全部通过。

通过这个示例我们可以看到,有了单元测试就能够在代码改动后快速进行回归测试,极大地提高开发效率并保证代码的质量。

跳过某些测试用例

为了节省时间支持在单元测试时跳过某些耗时的测试用例。

func TestTimeConsuming(t *testing.T) {
    if testing.Short() {
        t.Skip("short模式下会跳过该测试用例")
    }
    ...
}

当执行go test -short时就不会执行上面的TestTimeConsuming测试用例。

子测试

在上面的示例中我们为每一个测试数据编写了一个测试函数,而通常单元测试中需要多组测试数据保证测试的效果。Go1.7+ 中新增了子测试,支持在测试函数中使用t.Run执行一组测试用例,这样就不需要为不同的测试数据定义多个测试函数了。

func TestXXX(t *testing.T){
  t.Run("case1", func(t *testing.T){...})
  t.Run("case2", func(t *testing.T){...})
  t.Run("case3", func(t *testing.T){...})
}

表格驱动测试

介绍

编写好的测试并非易事,但在许多情况下,表格驱动测试可以涵盖很多方面:表格里的每一个条目都是一个完整的测试用例,包含输入和预期结果,有时还包含测试名称等附加信息,以使测试输出易于阅读。

使用表格驱动测试能够很方便的维护多个测试用例,避免在编写单元测试时频繁的复制粘贴。

表格驱动测试的步骤通常是定义一个测试用例表格,然后遍历表格,并使用t.Run对每个条目执行必要的测试。

表格驱动测试不是工具、包或其他任何东西,它只是编写更清晰测试的一种方式和视角。

示例

官方标准库中有很多表格驱动测试的示例,例如fmt包中的测试代码:

var flagtests = []struct {
 in  string
 out string
}{
 {"%a", "[%a]"},
 {"%-a", "[%-a]"},
 {"%+a", "[%+a]"},
 {"%#a", "[%#a]"},
 {"% a", "[% a]"},
 {"%0a", "[%0a]"},
 {"%1.2a", "[%1.2a]"},
 {"%-1.2a", "[%-1.2a]"},
 {"%+1.2a", "[%+1.2a]"},
 {"%-+1.2a", "[%+-1.2a]"},
 {"%-+1.2abc", "[%+-1.2a]bc"},
 {"%-1.2abc", "[%-1.2a]bc"},
}
func TestFlagParser(t *testing.T) {
 var flagprinter flagPrinter
 for _, tt := range flagtests {
  t.Run(tt.in, func(t *testing.T) {
   s := Sprintf(tt.in, &flagprinter)
   if s != tt.out {
    t.Errorf("got %q, want %q", s, tt.out)
   }
  })
 }
}

通常表格是匿名结构体数组切片,可以定义结构体或使用已经存在的结构进行结构体数组声明。name属性用来描述特定的测试用例。

接下来让我们试着自己编写表格驱动测试:

func TestSplitAll(t *testing.T) {
 // 定义测试表格
 // 这里使用匿名结构体定义了若干个测试用例
 // 并且为每个测试用例设置了一个名称
 tests := []struct {
  name  string
  input string
  sep   string
  want  []string
 }{
  {"base case", "a:b:c", ":", []string{"a", "b", "c"}},
  {"wrong sep", "a:b:c", ",", []string{"a:b:c"}},
  {"more sep", "abcd", "bc", []string{"a", "d"}},
  {"leading sep", "沙河有沙又有河", "沙", []string{"", "河有", "又有河"}},
 }
 // 遍历测试用例
 for _, tt := range tests {
  t.Run(tt.name, func(t *testing.T) { // 使用t.Run()执行子测试
   got := Split(tt.input, tt.sep)
   if !reflect.DeepEqual(got, tt.want) {
    t.Errorf("expected:%#v, got:%#v", tt.want, got)
   }
  })
 }
}

在终端执行go test -v,会得到如下测试输出结果:

❯ go test -v
=== RUN   TestSplit
--- PASS: TestSplit (0.00s)
=== RUN   TestSplitWithComplexSep
--- PASS: TestSplitWithComplexSep (0.00s)
=== RUN   TestSplitAll
=== RUN   TestSplitAll/base_case
=== RUN   TestSplitAll/wrong_sep
=== RUN   TestSplitAll/more_sep
=== RUN   TestSplitAll/leading_sep
--- PASS: TestSplitAll (0.00s)
    --- PASS: TestSplitAll/base_case (0.00s)
    --- PASS: TestSplitAll/wrong_sep (0.00s)
    --- PASS: TestSplitAll/more_sep (0.00s)
    --- PASS: TestSplitAll/leading_sep (0.00s)
PASS
ok      golang-unit-test-demo/base_demo 0.010s

并行测试

表格驱动测试中通常会定义比较多的测试case,在Go语言中很容易发挥自身并发优势将表格驱动测试并行化,可以查看下面的代码示例。

func TestSplitAll(t *testing.T) {
 t.Parallel()  // 将 TLog 标记为能够与其他测试并行运行
 // 定义测试表格
 // 这里使用匿名结构体定义了若干个测试用例
 // 并且为每个测试用例设置了一个名称
 tests := []struct {
  name  string
  input string
  sep   string
  want  []string
 }{
  {"base case", "a:b:c", ":", []string{"a", "b", "c"}},
  {"wrong sep", "a:b:c", ",", []string{"a:b:c"}},
  {"more sep", "abcd", "bc", []string{"a", "d"}},
  {"leading sep", "沙河有沙又有河", "沙", []string{"", "河有", "又有河"}},
 }
 // 遍历测试用例
 for _, tt := range tests {
  tt := tt  // 注意这里重新声明tt变量(避免多个goroutine中使用了相同的变量)
  t.Run(tt.name, func(t *testing.T) { // 使用t.Run()执行子测试
   t.Parallel()  // 将每个测试用例标记为能够彼此并行运行
   got := Split(tt.input, tt.sep)
   if !reflect.DeepEqual(got, tt.want) {
    t.Errorf("expected:%#v, got:%#v", tt.want, got)
   }
  })
 }
}

使用工具生成测试代码

社区里有很多自动生成表格驱动测试函数的工具,比如gotests等,很多编辑器如Goland也支持快速生成测试文件。这里简单演示一下gotests的使用。

安装

go get -u github.com/cweill/gotests/...

执行

gotests -all -w split.go

上面的命令表示,为split.go文件的所有函数生成测试代码至split_test.go文件(目录下如果事先存在这个文件就不再生成)。

生成的测试代码大致如下:

package base_demo
import (
 "reflect"
 "testing"
)
func TestSplit(t *testing.T) {
 type args struct {
  s   string
  sep string
 }
 tests := []struct {
  name       string
  args       args
  wantResult []string
 }{
  // TODO: Add test cases.
 }
 for _, tt := range tests {
  t.Run(tt.name, func(t *testing.T) {
   if gotResult := Split(tt.args.s, tt.args.sep); !reflect.DeepEqual(gotResult, tt.wantResult) {
    t.Errorf("Split() = %v, want %v", gotResult, tt.wantResult)
   }
  })
 }
}

代码格式与我们上面的类似,只需要在TODO位置添加我们的测试逻辑就可以了。

测试覆盖率

测试覆盖率是指代码被测试套件覆盖的百分比。通常我们使用的都是语句的覆盖率,也就是在测试中至少被运行一次的代码占总代码的比例。在公司内部一般会要求测试覆盖率达到80%左右。

Go提供内置功能来检查你的代码覆盖率。我们可以使用go test -cover来查看测试覆盖率。例如:

❯ go test -cover
PASS
coverage: 100.0% of statements
ok      golang-unit-test-demo/base_demo 0.009s

从上面的结果可以看到我们的测试用例覆盖了100%的代码。

Go还提供了一个额外的-coverprofile参数,用来将覆盖率相关的记录信息输出到一个文件。例如:

❯ go test -cover -coverprofile=c.out
PASS
coverage: 100.0% of statements
ok      golang-unit-test-demo/base_demo 0.009s

上面的命令会将覆盖率相关的信息输出到当前文件夹下面的c.out文件中。

❯ tree .
.
├── c.out
├── split.go
└── split_test.go

然后我们执行go tool cover -html=c.out,使用cover工具来处理生成的记录信息,该命令会打开本地的浏览器窗口生成一个HTML报告。

上图中每个用绿色标记的语句块表示被覆盖了,而红色的表示没有被覆盖。

testify/assert

testify是一个社区非常流行的Go单元测试工具包,其中使用最多的功能就是它提供的断言工具——testify/asserttestify/require

安装

go get github.com/stretchr/testify

使用示例

我们在写单元测试的时候,通常需要使用断言来校验测试结果,但是由于Go语言中没有提供断言,所以我们会写出很多的if...else...语句。而testify/assert为我们提供了很多常用的断言函数,并且能够输出友好、易于阅读的错误描述信息。

比如我们之前在TestSplit测试函数中就使用了reflect.DeepEqual来判断期望结果与实际结果是否一致。

t.Run(tt.name, func(t *testing.T) { // 使用t.Run()执行子测试
 got := Split(tt.input, tt.sep)
 if !reflect.DeepEqual(got, tt.want) {
  t.Errorf("expected:%#v, got:%#v", tt.want, got)
 }
})

使用testify/assert之后就能将上述判断过程简化如下:

t.Run(tt.name, func(t *testing.T) { // 使用t.Run()执行子测试
 got := Split(tt.input, tt.sep)
 assert.Equal(t, got, tt.want)  // 使用assert提供的断言函数
})

当我们有多个断言语句时,还可以使用assert := assert.New(t)创建一个assert对象,它拥有前面所有的断言方法,只是不需要再传入Testing.T参数了。

func TestSomething(t *testing.T) {
  assert := assert.New(t)
  // assert equality
  assert.Equal(123, 123, "they should be equal")
  // assert inequality
  assert.NotEqual(123, 456, "they should not be equal")
  // assert for nil (good for errors)
  assert.Nil(object)
  // assert for not nil (good when you expect something)
  if assert.NotNil(object) {
    // now we know that object isn't nil, we are safe to make
    // further assertions without causing any errors
    assert.Equal("Something", object.Value)
  }
}

testify/assert提供了非常多的断言函数,这里没办法一一列举出来,大家可以查看官方文档了解。

testify/require拥有testify/assert所有断言函数,它们的唯一区别就是——testify/require遇到失败的用例会立即终止本次测试。

此外,testify包还提供了mock、http等其他测试工具,篇幅所限这里就不详细介绍了,有兴趣的同学可以自己了解一下。

总结

本文介绍了Go语言单元测试的基本用法,通过为Split函数编写单元测试的真实案例,模拟了日常开发过程中的场景,一步一步详细介绍了表格驱动测试、回归测试和常用的断言工具testify/assert的使用。在下一篇中,我们将更进一步,详细介绍如何使用httptest和gock工具进行网络测试,更多关于Go语言单元测试基础的资料请关注我们其它相关文章!

(0)

相关推荐

  • Go语言单元测试超详细解析

    目录 一.单元测试分类及其概念 1.基本分类 2.细说单元测试分类 二.结合代码细说每一种测试 1.基准测试 2.组测试与子测试 三.pprof调试工具 1.对主函数进行传参 2.pprof性能调优 前言: 平时根据需求写代码.人工进行测试往往不会面面俱到,还会因为需求的改变繁琐的进行测试通过完成一个测试函数,可以大大简化测试的步骤,并且在需求该变的时候只需要改变一下测试的输入与期望 一.单元测试分类及其概念 1.基本分类 测试函数 函数前缀为Test 主要用于测试程序的一些逻辑行为是否正确 基

  • Golang单元测试与覆盖率的实例讲解

    1 概述 C/C++和Java(以及大多数的主流编程语言)都有自己成熟的单元测试框架,前者如Check,后者如JUnit,但这些编程框架本质上仍是第三方产品,为了执行单元测试,我们不得不从头开始搭建测试工程,并且需要依赖于第三方工具才能生成单元测试的覆盖率. 相比之下,Go语言官方则提供了语言级的单元测试支持,即testing包,而且仅通过go工具本身就可以方便地生成覆盖率数据,也就是说,单元测试是Go语言的自带属性,除了好好设计自己的单元测试用例外,开发者不需要操心工程搭建的任何细节.没错,G

  • Go语言基础单元测试与性能测试示例详解

    目录 概述 单元测试 代码说明如下 问题 注意 性能测试 基本使用 自定义测试时间 概述 测试不是Go语言独有的,其实在很多语言都有测试,例如:Go.Java.Python- 要想成为一名合格的大牛,这是程序员必须具备的一项技能,特别是一些大公司,这是加分的一项,主要有如下优点: 代码可以随时测试,保证代码不会产生错误 写出更加高效的代码 testing文档 Testing_flags文档 单元测试 格式:func TestXXX(t *testing.T) //add.go package c

  • golang 对私有函数进行单元测试的实例

    在待测试的私有函数所在的包内,新建一个xx_test.go文件 书写方式如下: import ( "github.com/stretchr/testify/assert" "testing" ) var XXFunc = yourPrivateFunc func TestXXFunc(t *testing.T) { ret, ... := XXFunc(...) assert.Equal(t, ret, ...) } 就可以了~ 补充:golang test使用(简

  • django写单元测试的方法

       从网上找了很多django单元测试的案例,感觉不是很好用,于是自己写了一套测试方法,在测试环境我们只需要传uri .请求方式.参数即可一键对所有接口进行测试. 一.使用requests模拟Http请求    假设你执行成功的返回的json格式如下: { "code": 0, "message": "OK", "data": { "first": false, "token": &q

  • Go语言单元测试基础从入门到放弃

    目录 Go语言测试 go test工具 单元测试函数 格式 单元测试示例 go test -v go test -run 回归测试 跳过某些测试用例 子测试 表格驱动测试 介绍 示例 并行测试 使用工具生成测试代码 测试覆盖率 testify/assert 安装 使用示例 总结 Go语言测试 这是Go单测从入门到放弃系列教程的第0篇,主要讲解在Go语言中如何做单元测试以及介绍了表格驱动测试.回归测试,并且介绍了常用的断言工具. go test工具 Go语言中的测试依赖go test命令.编写测试

  • C语言文件操作零基础新手入门保姆级教程

    目录 一.前言 二.文件操作基础知识 ①什么是文件 ②数据文件类型 ③数据如何存储 ④如何读取二进制文件 ⑤什么是文件名 ⑥文件缓冲区 ⑦文件指针 三.文件操作函数 ①fopen 与 fclose ②fputc与fgetc ③fputs与fgets ④fprintf与fscanf ⑤fwrite与fread ⑥fseek与ftell与rewind ⑦ferror与feof ⑧补充函数 sscanf sprintf ⑨补充函数perror  strerror 总结 一.前言 我们如何使我们设计的程

  • Go语言单元测试模拟服务请求和接口返回

    目录 前言 httptest gock 安装 使用示例 总结 前言 这是Go单元测试从入门到放弃系列教程的第1篇,介绍了如何使用httptest和gock工具进行网络测试. 在上一篇<Go单元测试从入门到放弃—0.单元测试基础>中,我们介绍了Go语言编写单元测试的基础内容. 而实际工作中的业务场景往往会比较复杂,无论我们的代码是作为server端对外提供服务或者还是我们依赖别人提供的网络服务(调用别人提供的API接口)的场景,我们通常都不想在测试过程中真正的建立网络连接.本文就专门介绍如何在上

  • EJB基础知识(入门必看)

    什么是EJB 可移植的,可重用的,可伸缩的业务应用程序的平台 为什么选择EJB 1. 易用性, 由EJB容器提供许多的服务, 开发人员只需要关注业务本身即可 2. 集成解决方案套装, 由应用服务器提供大量服务 3. 开放的JavaEE标准 4. 广泛的厂商支持 5. 稳定, 高质量的代码基础 6. 集群, 负载均衡, 故障转移 7. 易于开发允许可重用的组件 EJB容器提供的服务 1. 集成 2. 池化 3. 线程安全 4. 状态管理(针对有状态会话bean) 5. 消息服务器(针对消息驱动be

  • JavaScript基础教程——入门必看篇

    JavaScript他是一种描述性语言,其实他并不难学,只要用心学,一定会学好,我相信大家在看这篇文章的时候,一定也学过HTML吧,使用JavaScript就是为了能和网页有更好的交互,下面切入主题. 一. JavaScript 1.什么是JavaScript JavaScript是一种描述性语言,也是一种基于对象(Object)和事件驱动(Event Driven)的,并具有安全性的脚本语言. 2.JavaScript的特点 JavaScript主要用来向HTML页面添加交互行为. JavaS

  • 详解MySQL从入门到放弃-安装

    学习内容 1.软件安装及服务器设置. 2.(选做,但是强烈建议) 使用图形界面软件 Navicat for SQL 3.数据库基础知识 数据库定义 关系型数据库 二维表 行 列 主键 外键 4.MySQL数据库管理系统 数据库 数据表 视图 存储过程 软件安装 MySQL下载链接:MySQL 下载第一个,之后解压缩. 我的目录在C:\Users\Public\MySQL,之后在该文件夹配置my.ini 接下来启动MySQL,在cmd中操作 cd C:\Users\Public\MySQL\bin

  • 通俗易懂的Redis数据结构基础教程(入门)

    Redis有5个基本数据结构,string.list.hash.set和zset.它们是日常开发中使用频率非常高应用最为广泛的数据结构,把这5个数据结构都吃透了,你就掌握了Redis应用知识的一半了. string 首先我们从string谈起.string表示的是一个可变的字节数组,我们初始化字符串的内容.可以拿到字符串的长度,可以获取string的子串,可以覆盖string的子串内容,可以追加子串. Redis的字符串是动态字符串,是可以修改的字符串,内部结构实现上类似于Java的ArrayL

  • MySQL基础快速入门知识总结(附思维导图)

    目录 前言 一.数据库基础知识 1.什么是数据库 2.数据库的分类 3.数据库的常用语言 4.数据库的常用操作方式 5.MySQL的架构 二.数据库的增删改查 1.创建数据库 2.查询数据库 3.修改数据库 4.删除数据库 三.表的增删改查 1.创建表 2.查询表 3.修改表 4.删除表 四.记录的增删改查 1.插入记录 2.查询记录(最常用) 3.修改记录 4.删除记录 五.字段类型 1.数字型 1.1整数型 1.2小数型 2.文本型 3.日期时间 六.字段属性 总结 前言 本文是我这段时间自

  • CGO编程基础快速入门

    目录 带你了解CGO编程 快速入门 CGO基础 import "C" 语句 带你了解CGO编程 大学时最开始学的语言莫过于C/C++,C/C++经过几十年的发展,已经积累了庞大的软件资产,它们很多久经考验而且性能已经足够优化.Go语言则是站在巨人的肩膀之上而诞生,go也自带一个CGO的工具来支持C语言函数的调用,同时我们可以用GO语言导出C动态库接口给其他语言使用 快速入门 我们先通过一个简单的CGO程序来了解Go中的C package main import "C"

  • 无线标记语言(WML)基础之WMLScript 基础第1/2页

    WML Script是属于无限应用协议WAP应用层的一部分,使用它可以向WML卡片组和卡片中添加客户端的处理逻辑,目前最新的版本是1.1版.WML Script1.1是在欧洲计算机制造商协议会制定的ECMAScript脚本语言的基础上,经过修改和优化而指定的.它能够更好的支持诸如移动电话类的乍带宽通信设备,在WML编程中使用WML Script可以有效的增强客户端应用的灵活性,而且,我们也可以把WML Script作为一个工具使用,开发出功能强大的WAP网络应用和无限网页.本章我们将详细讲解WM

随机推荐