首页 > 编程语言 >云原生时代崛起的编程语言Go常用标准库实战

云原生时代崛起的编程语言Go常用标准库实战

时间:2023-05-05 22:33:06浏览次数:53  
标签:原生 编程语言 err fmt Println Go main string

@

目录

基础标准库

简述

Go语言的标准库覆盖网络、系统、加密、编码、图形等各个方面,可以直接使用标准库的 http 包进行 HTTP 协议的收发处理;网络库基于高性能的操作系统通信模型(Linux 的 epoll、Windows 的 IOCP);所有的加密、编码都内建支持,无需要再从第三方开发者处获取;Go 语言的编译器也是标准库的一部分,通过词法器扫描源码,使用语法树获得源码逻辑分支等;Go 语言的周边工具也是建立在这些标准库上。在标准库上可以完成几乎大部分的需求,Go 语言的标准库以包的方式提供支持,下表是 Go 语言标准库中常见的包及其功能。

Go语言标准库包名 功 能
bufio 带缓冲的 I/O 操作
bytes 实现字节操作
container 封装堆、列表和环形列表等容器
crypto 加密算法
database 数据库驱动和接口
debug 各种调试文件格式访问及调试功能
encoding 常见算法如 JSON、XML、Base64 等
flag 命令行解析
fmt 格式化操作
go Go 语言的词法、语法树、类型等。可通过这个包进行代码信息提取和修改
html HTML 转义及模板系统
image 常见图形格式的访问及生成
io 实现 I/O 原始访问接口及访问封装
log 用于日志记录和控制台输出
math 数学库
net 网络库,支持 Socket、HTTP、邮件、RPC、SMTP 等
os 操作系统平台不依赖平台操作封装
path 兼容各操作系统的路径操作实用函数
plugin Go 1.7 加入的插件系统。支持将代码编译为插件,按需加载
reflect 语言反射支持。可以动态获得代码中的类型信息,获取和修改变量的值
regexp 正则表达式封装
runtime 运行时接口
sort 排序接口
strings 字符串转换、解析及实用函数
sync 提供同步原语,如互斥锁和条件变量(上篇文章有专门讲解)
time 时间接口
text 文本模板及 Token 词法器

字符串-string

底层结构

标准库的strings包提供了许多有用的与字符串相关的函数。Go字符串底层的数据结构在runtime/strings.go中定义如下:

image-20230505092653839

从上面的stringStruct结构体得知其包含两个字段,一个是8个字节的万能指针,指向一个数组,数组里面存储就是实际的字符,另一个则是一个8个字节表示其长度,因此不管anyStrings多长通过unsafe.Sizeof("anyStrings")最终获取大小都是固定的16个字节。

image-20230505093428038

函数

下面是一些常见函数举例,可以到strings包文档中找到更多的函数

package main

import (
	"fmt"
	s "strings"
	"unsafe"
)

var p = fmt.Println

func main() {
	p(unsafe.Sizeof("anyStrings"))
	p(unsafe.Sizeof("anyStringsMoreThenLength"))
	p("Contains:  ", s.Contains("test", "es"))
	p("Count:     ", s.Count("test", "t"))
	p("HasPrefix: ", s.HasPrefix("test", "te"))
	p("HasSuffix: ", s.HasSuffix("test", "st"))
	p("Index:     ", s.Index("test", "e"))
	p("Join:      ", s.Join([]string{"a", "b"}, "-"))
	p("Repeat:    ", s.Repeat("a", 5))
	p("Replace:   ", s.Replace("foo", "o", "0", -1))
	p("Replace:   ", s.Replace("foo", "o", "0", 1))
	p("Split:     ", s.Split("a-b-c-d-e", "-"))
	p("ToLower:   ", s.ToLower("TEST"))
	p("ToUpper:   ", s.ToUpper("test"))
}

image-20230505093738945

长度

  • Go 语言的内建函数 len(),可以用来获取切片、字符串、通道(channel)等的长度,
  • Go 语言的字符串都以 UTF-8 格式保存,每个中文占用 3 个字节,因此使用 len() 获得两个中文文字对应的 6 个字节;
  • 针对ASCII 字符串长度使用 len() 函数,Unicode 字符串长度使用 utf8.RuneCountInString() 函数。如果没有使用 Unicode,汉字则显示为乱码。
  • ASCII 字符串遍历直接使用下标;Unicode 字符串遍历用 for range
  • bytes.Buffer实现字符串拼接。
package main

import (
	"bytes"
	"fmt"
	"unicode/utf8"
)

var p = fmt.Println

func main() {
	str1 := "Hello World!"
	str2 := "你好"
	fmt.Println(len(str1))                          // 12
	fmt.Println(len(str2))                          // 6
	fmt.Println(utf8.RuneCountInString(str2))       // 2
	fmt.Println(utf8.RuneCountInString("你好,world")) // 8

	// 声明字节缓冲
	var stringBuilder bytes.Buffer
	// 把字符串写入缓冲
	stringBuilder.WriteString(str1)
	stringBuilder.WriteString(str2)
	// 将缓冲以字符串形式输出
	fmt.Println(stringBuilder.String())

	theme := "狙击 start"
	for i := 0; i < len(theme); i++ {
		fmt.Printf("ascii: %c  %d\n", theme[i], theme[i])
	}

	for _, s := range theme {
		fmt.Printf("Unicode: %c  %d\n", s, s)
	}
}

image-20230505100058382

格式化输出

Go为传统的printf字符串格式化提供了很好的支持,Go提供了若干个打印“动词”,用于格式化一般Go值,下面是一些常见的字符串格式化任务的示例。

package main

import (
	"fmt"
	"os"
)

type point struct {
	x, y int
}

func main() {

	p := point{1, 2}
	fmt.Printf("struct1: %v\n", p)

	fmt.Printf("struct2: %+v\n", p)

	fmt.Printf("struct3: %#v\n", p)

	fmt.Printf("type: %T\n", p)

	fmt.Printf("bool: %t\n", true)

	fmt.Printf("int: %d\n", 123)

	fmt.Printf("bin: %b\n", 14)

	fmt.Printf("char: %c\n", 33)

	fmt.Printf("hex: %x\n", 456)

	fmt.Printf("float1: %f\n", 78.9)

	fmt.Printf("float2: %e\n", 123400000.0)
	fmt.Printf("float3: %E\n", 123400000.0)

	fmt.Printf("str1: %s\n", "\"string\"")

	fmt.Printf("str2: %q\n", "\"string\"")

	fmt.Printf("str3: %x\n", "hex this")

	fmt.Printf("pointer: %p\n", &p)

	fmt.Printf("width1: |%6d|%6d|\n", 12, 345)

	fmt.Printf("width2: |%6.2f|%6.2f|\n", 1.2, 3.45)

	fmt.Printf("width3: |%-6.2f|%-6.2f|\n", 1.2, 3.45)

	fmt.Printf("width4: |%6s|%6s|\n", "foo", "b")

	fmt.Printf("width5: |%-6s|%-6s|\n", "foo", "b")

	s := fmt.Sprintf("sprintf: a %s", "string")
	fmt.Println(s)

	fmt.Fprintf(os.Stderr, "io: an %s\n", "error")
}

image-20230505100238779

模版-template

text/template

Golang中的标准库template就像是一个“脚本语言解析器”,其中涉及到变量赋值、函数/方法调用和各种条件/循环控制结构等。template包实现了数据驱动的用于生成文本输出的模板,简单来说就是将一组文本嵌入另一组文本模版中,返回一个期望的文本。Go为模板操作提供了丰富的支持。嵌套模板,导入函数,表示变量,迭代数据等等都很简单。如果需要比CSV数据格式更复杂的东西,模板可能是一个不错的解决方案。模板的另一个应用是网站的页面渲染;当我们想要将服务器端数据呈现给客户端时,模板可以很好地满足要求。

Go提供了text/template和html/template这两个模板包,这两个包的部分函数看起来非常相似,实际功能也确实如此

package main

import (
	"os"
	"text/template"
)

type Inventory struct {
	Username string
	Phone    uint
	Tag      bool
	Sex      string
}

func main() {
	t1 := template.New("t1")
	t1, err := t1.Parse("Value is {{.}}\n")
	if err != nil {
		panic(err)
	}

	t1 = template.Must(t1.Parse("Value: {{.}}\n"))

	t1.Execute(os.Stdout, "some text")
	t1.Execute(os.Stdout, 5)
	t1.Execute(os.Stdout, []string{
		"Go",
		"Rust",
		"C++",
		"C#",
	})

	Create := func(name, t string) *template.Template {
		return template.Must(template.New(name).Parse(t))
	}

	t2 := Create("t2", "Name: {{.Name}}\n")

	t2.Execute(os.Stdout, struct {
		Name string
	}{"Jane Doe"})

	t2.Execute(os.Stdout, map[string]string{
		"Name": "Mickey Mouse",
	})

	t3 := Create("t3",
		"{{if . -}} yes {{else -}} no {{end}}\n")
	t3.Execute(os.Stdout, "not empty")
	t3.Execute(os.Stdout, "")

	t4 := Create("t4",
		"Range: {{range .}}{{.}} {{end}}\n")
	t4.Execute(os.Stdout,
		[]string{
			"Go",
			"Rust",
			"C++",
			"C#",
		})

	sweaters := Inventory{"移动", 10086, false, "难"}

	content := `{{.Phone}} of {{.Username}} {{if .Tag }} tag=true {{else}}   tag=false {{end}}`
	tmpl, err := template.New("test").Parse(content)
	//{{.Phone}}获取的是struct对象中的Phone字段的值
	if err != nil {
		panic(err)
	}
	err = tmpl.Execute(os.Stdout, sweaters) // 10086 of 移动  tag=true
	if err != nil {
		panic(err)
	}
}

image-20230505104701798

html/template

使用html/template来呈现网站,模板是纯文本,但变量和函数可以在大括号块内使用,模板包还提供了处理文件的便捷方法。html/template包是对text/template包的包装,因此能同于text/template基本都对html/template包同样适用,除了import语句无需其他任何修改。HTML模板提供了上下文感知安全性的额外好处,也可以防止诸如JavaScript注入之类的事情。如果要生成HTML格式的输出,参见html/template包,该包提供了和本包相同的接口,但会自动将输出转化为安全的HTML格式输出,可以抵抗一些网络攻击。

package main

import (
	"html/template"
	"net/http"
)

func tmpl(w http.ResponseWriter, r *http.Request) {
	t1, err := template.ParseFiles("test.html")
	if err != nil {
		panic(err)
	}
	t1.Execute(w, "hello world")
}

func main() {
	server := http.Server{
		Addr: "127.0.0.1:8080",
	}
	http.HandleFunc("/tmpl", tmpl)
	server.ListenAndServe()
}

创建test.html

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>Go Web</title>
</head>
<body>
{{ . }}
</body>
</html>

访问测试地址http://localhost:8080/tmpl

image-20230505105330299

正则表达式-regexp

Go提供了对正则表达式的内置支持,其由regexp包实现了正则表达式搜索;Go标准库使用RE2语法,RE2语法也是Python、C和Perl使用的正则表达式语法,常见函数:

  • MatchString:regexp.MatchString()用来匹配子字符串。下面这个例子是检查字符串是否以Golang开头。我们使用^来匹配字符串中以文本的开始。我们使用^Golang作为正则表达式进行匹配。
  • Compile:Compile() 或者 MustCompile()创建一个编译好的正则表达式对象。假如正则表达式非法,那么Compile()方法会返回error,而MustCompile()编译非法正则表达式时不会返回error,而是会panic。如果你想要很好的性能,不要在使用的时候才调用Compile()临时进行编译,而是预先调用Compile()编译好正则表达式对象。
  • FindString:FindString()用来返回第一个匹配的结果。如果没有匹配的字符串,那么它会返回一个空的字符串,当然如果你的正则表达式就是要匹配空字符串的话,它也会返回空字符串。使用 FindStringIndex 或者 FindStringSubmatch可以区分这两种情况。
    • FindStringIndex:FindStringIndex()可以得到匹配的字符串在整体字符串中的索引位置。如果没有匹配的字符串,它会返回nil值。
    • FindStringSubmatch:FindStringSubmatch() 除了返回匹配的字符串外,还会返回子表达式的匹配项。如果没有匹配项,则返回nil值。
  • FindAllString:FindString方法的All版本,它返回所有匹配的字符串的slice。如果返回nil值代表没有匹配的字符串。
  • ReplaceAllString :用来替换所有匹配的字符串,返回一个源字符串的拷贝。

Go中与regexp相关的一些常见示例

package main

import (
	"bytes"
	"fmt"
	"regexp"
)

func main() {

	match, _ := regexp.MatchString("p([a-z]+)ch", "peach")
	fmt.Println(match)

	r, _ := regexp.Compile("p([a-z]+)ch")

	fmt.Println(r.MatchString("peach"))

	fmt.Println(r.FindString("peach punch"))

	fmt.Println("idx:", r.FindStringIndex("peach punch"))

	fmt.Println(r.FindStringSubmatch("peach punch"))

	fmt.Println(r.FindStringSubmatchIndex("peach punch"))

	fmt.Println(r.FindAllString("peach punch pinch", -1))

	fmt.Println("all:", r.FindAllStringSubmatchIndex(
		"peach punch pinch", -1))

	fmt.Println(r.FindAllString("peach punch pinch", 2))

	fmt.Println(r.Match([]byte("peach")))

	r = regexp.MustCompile("p([a-z]+)ch")
	fmt.Println("regexp:", r)

	fmt.Println(r.ReplaceAllString("a peach", "<fruit>"))

	in := []byte("a peach")
	out := r.ReplaceAllFunc(in, bytes.ToUpper)
	fmt.Println(string(out))
}

image-20230505112943707

编码-encoding

encoding 包是 Go 标准库中的一个重要包,主要用于数据编码和解码。encoding 包中包含了许多常用的数据编码和解码算法,如 JSON、XML、CSV、Base64 等,这些算法可以帮助我们将数据从一种格式转换为另一种格式,便于在不同的系统之间传输和处理。

Base64

Go提供对base64编码/解码的内置支持。

package main

import (
	b64 "encoding/base64"
	"fmt"
)

func main() {

	data := "abc123!?$*&()'-=@~"

	sEnc := b64.StdEncoding.EncodeToString([]byte(data))
	fmt.Println(sEnc)

	sDec, _ := b64.StdEncoding.DecodeString(sEnc)
	fmt.Println(string(sDec))
	fmt.Println()

	uEnc := b64.URLEncoding.EncodeToString([]byte(data))
	fmt.Println(uEnc)
	uDec, _ := b64.URLEncoding.DecodeString(uEnc)
	fmt.Println(string(uDec))
}

image-20230505151716877

JSON

Go提供了对JSON编码和解码的内置支持,包括来自内置和自定义数据类型的支持。需要使用encoding/json包进行json实现序列化与反序列化,go的json解析主要是编码和解码两个函数,序列化也就是由结构体转化为json string字符串,使用json.Marshal函数;反序列化就是将json string字符串转化为结构体,使用函数json.Unmarshal函数完成。

~~~go
package main

import (
	"encoding/json"
	"fmt"
	"os"
)

type response1 struct {
	Page   int
	Fruits []string
}

type response2 struct {
	Page   int      `json:"page"`
	Fruits []string `json:"fruits"`
}

func main() {

	bolB, _ := json.Marshal(true)
	fmt.Println(string(bolB))

	intB, _ := json.Marshal(1)
	fmt.Println(string(intB))

	fltB, _ := json.Marshal(2.34)
	fmt.Println(string(fltB))

	strB, _ := json.Marshal("gopher")
	fmt.Println(string(strB))

	slcD := []string{"apple", "peach", "pear"}
	slcB, _ := json.Marshal(slcD)
	fmt.Println(string(slcB))

	mapD := map[string]int{"apple": 5, "lettuce": 7}
	mapB, _ := json.Marshal(mapD)
	fmt.Println(string(mapB))

	res1D := &response1{
		Page:   1,
		Fruits: []string{"apple", "peach", "pear"}}
	res1B, _ := json.Marshal(res1D)
	fmt.Println(string(res1B))

	res2D := &response2{
		Page:   1,
		Fruits: []string{"apple", "peach", "pear"}}
	res2B, _ := json.Marshal(res2D)
	fmt.Println(string(res2B))

	byt := []byte(`{"num":6.13,"strs":["a","b"]}`)

	var dat map[string]interface{}

	if err := json.Unmarshal(byt, &dat); err != nil {
		panic(err)
	}
	fmt.Println(dat)

	num := dat["num"].(float64)
	fmt.Println(num)

	strs := dat["strs"].([]interface{})
	str1 := strs[0].(string)
	fmt.Println(str1)

	str := `{"page": 1, "fruits": ["apple", "peach"]}`
	res := response2{}
	json.Unmarshal([]byte(str), &res)
	fmt.Println(res)
	fmt.Println(res.Fruits[0])

	enc := json.NewEncoder(os.Stdout)
	d := map[string]int{"apple": 5, "lettuce": 7}
	enc.Encode(d)
}

image-20230505135300690

XML

Go通过encoding.xml包提供了对XML和类XML格式的内置支持。Go语言内置的 encoding/xml 包可以用在结构体和 XML 格式之间进行编解码,其方式跟 encoding/json 包类似;然而与 JSON 相比 XML 的编码和解码在功能上更苛刻得多,这是由于 encoding/xml 包要求结构体的字段包含格式合理的标签,而 JSON 格式却不需要。

package main

import (
	"encoding/xml"
	"fmt"
)

type Plant struct {
	XMLName xml.Name `xml:"plant"`
	Id      int      `xml:"id,attr"`
	Name    string   `xml:"name"`
	Origin  []string `xml:"origin"`
}

func (p Plant) String() string {
	return fmt.Sprintf("Plant id=%v, name=%v, origin=%v",
		p.Id, p.Name, p.Origin)
}

func main() {
	coffee := &Plant{Id: 27, Name: "Coffee"}
	coffee.Origin = []string{"Ethiopia", "Brazil"}

	out, _ := xml.MarshalIndent(coffee, " ", "  ")
	fmt.Println(string(out))

	fmt.Println(xml.Header + string(out))

	var p Plant
	if err := xml.Unmarshal(out, &p); err != nil {
		panic(err)
	}
	fmt.Println(p)

	tomato := &Plant{Id: 81, Name: "Tomato"}
	tomato.Origin = []string{"Mexico", "California"}

	type Nesting struct {
		XMLName xml.Name `xml:"nesting"`
		Plants  []*Plant `xml:"parent>child>plant"`
	}

	nesting := &Nesting{}
	nesting.Plants = []*Plant{coffee, tomato}

	out, _ = xml.MarshalIndent(nesting, " ", "  ")
	fmt.Println(string(out))
}

image-20230505135543401

时间-time

在编程中经常会遭遇八小时时间差问题,这是由时区差异引起的,为了能更好地解决它们,需要先理解几个时间定义标准。

  • GMT(Greenwich Mean Time):格林威治时间;GMT 根据地球的自转和公转来计算时间,它规定太阳每天经过位于英国伦敦郊区的皇家格林威治天文台的时间为中午12点;GMT 是前世界标准时。
  • UTC(Coordinated Universal Time),协调世界时间,又称世界统一时间;UTC 比 GMT 更精准,它根据原子钟来计算时间,适应现代社会的精确计时。在不需要精确到秒的情况下,可以认为 UTC=GMT;UTC 是现世界标准时。

适应现代社会的精确计时从格林威治本初子午线起,往东为正,往西为负,全球共划分为 24 个标准时区,相邻时区相差一个小时;如何获取自Unix纪元以来的秒数、毫秒数或纳秒数和时间格式化。

package main

import (
	"fmt"
	"time"
)

func main() {
	p := fmt.Println

	now := time.Now()
	p(now)

	then := time.Date(
		2009, 11, 17, 20, 34, 58, 651387237, time.UTC)
	p(then)

	p(then.Year())
	p(then.Month())
	p(then.Day())
	p(then.Hour())
	p(then.Minute())
	p(then.Second())
	p(then.Nanosecond())
	p(then.Location())

	p(then.Weekday())

	p(then.Before(now))
	p(then.After(now))
	p(then.Equal(now))

	diff := now.Sub(then)
	p(diff)

	p(diff.Hours())
	p(diff.Minutes())
	p(diff.Seconds())
	p(diff.Nanoseconds())

	p(then.Add(diff))
	p(then.Add(-diff))
	p("-----------------------")
	fmt.Println(now.Unix())
	fmt.Println(now.UnixMilli())
	fmt.Println(now.UnixNano())

	fmt.Println(time.Unix(now.Unix(), 0))
	fmt.Println(time.Unix(0, now.UnixNano()))
	p("-----------------------")
	t := time.Now()
	p(t.Format(time.RFC3339))

	t1, e := time.Parse(
		time.RFC3339,
		"2012-11-01T22:08:41+00:00")
	p(t1)

	p(t.Format("3:04PM"))
	p(t.Format("Mon Jan _2 15:04:05 2006"))
	p(t.Format("2006-01-02T15:04:05.999999-07:00"))
	form := "3 04 PM"
	t2, e := time.Parse(form, "8 41 PM")
	p(t2)

	fmt.Printf("%d-%02d-%02dT%02d:%02d:%02d-00:00\n",
		t.Year(), t.Month(), t.Day(),
		t.Hour(), t.Minute(), t.Second())

	ansic := "Mon Jan _2 15:04:05 2006"
	_, e = time.Parse(ansic, "8:41PM")
	p(e)
}

image-20230505181055251

网络-net

网络编程是go语言使用的一个核心模块;golang的网络封装使用对于底层socket或者上层的http,甚至是web服务都很友好。net包提供了可移植的网络I/O接口,包括TCP/IP、UDP、域名解析和Unix域socket等方式的通信。其中每一种通信方式都使用 xxConn 结构体来表示,诸如IPConn、TCPConn等,这些结构体都实现了Conn接口,Conn接口实现了基本的读、写、关闭、获取远程和本地地址、设置timeout等功能。

URL

url提供了一种统一的方式来定位资源,Go中解析url需要使用到其net包。

相关文章

  • mongodb使用and配合or查询
    使用mongodb时,有时需要使用and配合(嵌套)or查询。实现类似以下sql的语句:select*fromMongoDbTestwherestatus=1and(userId="abc"orprice>=2)对应的mongodb语句如下:db.getCollection("mongoDbTest").find({"status":1,"$and":[{"$or&q......
  • SpringBoot配置mongodb打印日志
    在application.yml添加配置:logging:level:org.springframework.data.mongodb.core.MongoTemplate:DEBUG如果使用的是application.properties,则是:logging.level.org.springframework.data.mongodb.core.MongoTemplate=DEBUG......
  • Go笔记(十三):包管理工具
    包管理工具,用来管理模块中包的依赖关系。下面来看看gomod的使用方法。1.1、初始化模块gomodinit项目模块名1.2、依赖关系处理,根据go.mod文件gomodtidy1.3、将依赖复制到项目下的vendor目录gomodvendor如果包被屏蔽(墙),随后使用gobuild-mod=vendo......
  • Go笔记(十二):接口
    1、接口的声明Go语言中的接口是一种新的类型定义,拥有将具有共性的方法定义在一起的特性。任何其他类型只要实现了这些方法就是实现了这个接口。语法详情如下:/*定义接口*/typeinterface_nameinterface{method_name1[return_type]method_name2[return_type]......
  • Go笔记(十一):方法
    Go语言没有Java语言面向对象的特性,也无类对象的概念。但可以使用结构体实现这些特性。1、方法的声明Go中的方法是一种特殊的函数,与struct相关联,被称为struct的接收者。可以理解为方法就是有接收者的函数。语法格式如下:typemystructstruct{}func(recvmystruct)my......
  • Python 脚本部署和发布 Django 应用程序的示例代码及注释
    代码说明:1、在脚本中定义了要部署的Django应用程序名称、Docker镜像名称和标签。2、使用字符串模板定义了KubernetesDeployment和Service的YAML文件。在字符串模板中使用了变量,用于替换实际的值。3、将Deployment和Service的YAML文件保存到本地文件中,并使用kube......
  • Jenkins 执行Docker build错误Got permission denied while trying to connect to the
    问题: 解决方法:这个报错为权限问题1.把jenkins用户,加到docker用户组 #如果没有docker用户组,先创建用户组:groupadddocker#添加jenkins用户到用户组:sudousermod-a-Gdockerjenkins-a<追加>必须与-G选项一起使用,把用户追加到某些组中。-G<群组>修改用户所属的......
  • django迁移数据库错误问题解决
    删除所有的pyc文件,迁移文件然后重新运行python3manage.pymakemigrationsdjango.db.utils.InternalError:(1060,"Duplicatecolumnname'addr_id'")运行python3manage.pymigrate--fake然后重新运行python3manage.pymigrate成功!......
  • Django框架——ajax补充、多对多三种创建、序列化组件、批量操作数据、分页器
    ajax补充说明主要是针对回调函数args接收到的响应数据1.后端request.is_ajax() 用于判断当前请求是否由ajax发出2.后端返回的三板斧都会被args接收不再影响整个浏览器页面3.选择使用ajax做前后端交互的时候后端一般返回的都是字典数据 user_dict={'code':10000,'usernam......
  • Django——基于forms组件和ajax的注册功能
    Django——基于forms组件和ajax的注册功能path('register/',views.register)#注册的form表单fromdjangoimportformsfromdjango.formsimportwidgetsclassRegForm(forms.Form):user=forms.CharField(max_length=32,widget=widgets.TextInput(attrs={'class&......