Go语言教程之边写边学:web应用:读取和写入JSON数据的Web应用程序

在此示例中,我们将通过用户界面表单读取-写入-更新JSON文件中的JSON数据,获取特定记录的数据并删除特定记录的数据。

net/http标准库包提供了多种创建HTTP服务器的方法,并附带了一个基本的路由器。此处使用的net/http包用于向服务器发出请求并响应请求。

 

项目目录结构:

 

 

示例代码:main.go

导入net/http包。包http提供HTTP客户端和服务器实现。在main函数中,使用HandleFunc方法创建路由 /。HandleFunc为给定模式注册处理程序函数。HandleFunc阻止我们在执行处理程序之前和之后使用中间件执行任务。ListenAndServe使用给定的地址和处理程序启动HTTP服务器。

package main

import (
	handlers "./handlers"
	"net/http"
)

func main() {
	http.HandleFunc("/addnewuser/", handlers.AddNewUserFunc)
	http.HandleFunc("/notsucceded", handlers.NotSucceded)

	http.HandleFunc("/deleted", handlers.DeletedFunc)
	http.HandleFunc("/deleteuser/deleted", handlers.DeleteUserFunc)
	http.HandleFunc("/deleteuser/", handlers.DeleteUserServe)
	http.HandleFunc("/deleteuser/notsuccededdelete", handlers.NotSuccededDelete)

	http.HandleFunc("/", handlers.IndexFunc)

	http.HandleFunc("/showuser/show", handlers.ShowUserFunc)
	http.HandleFunc("/showuser/", handlers.ShowUser)
	http.HandleFunc("/showuser/notsuccededshow/", handlers.NotSuccededShow)

	http.ListenAndServe(":8080", nil)
}

 

示例代码:list.json

[
 {
  "id": 1,
  "firstName": "Mariya",
  "lastName": "Ivanova",
  "balance": 300
 },
 {
  "id": 2,
  "firstName": "EKatina",
  "lastName": "Milevskaya",
  "balance": 5000
 },
 {
  "id": 3,
  "firstName": "Vasek",
  "lastName": "Zalupickiy",
  "balance": 2000
 }
]

 

示例代码:handlers\handlers.go

package handlers

import (
	model "../model"
	"encoding/json"
	"fmt"
	"html/template"
	"io/ioutil"
	"net/http"
	"os"
	"regexp"
	"strconv"
)

//function to check correct user adding input (regular expression and non-empty field input)
func checkFormValue(w http.ResponseWriter, r *http.Request, forms ...string) (res bool, errStr string) {
	for _, form := range forms {
		m, _ := regexp.MatchString("^[a-zA-Z]+$", r.FormValue(form))
		if r.FormValue(form) == "" {
			return false, "All forms must be completed"
		}
		if m == false {
			return false, "Use only english letters if firstname,lastname forms"
		}

	}
	return true, ""
}

func ShowUser(w http.ResponseWriter, r *http.Request) {
	http.ServeFile(w, r, "templates/showUser.html")
}

func NotSuccededShow(w http.ResponseWriter, r *http.Request) {
	http.ServeFile(w, r, "templates/notSuccededShow.html")

}

//handler to show user with id input
func ShowUserFunc(w http.ResponseWriter, r *http.Request) {
	if r.Method == "GET" {
		t, _ := template.ParseFiles("templates/showUserPage.html")
		t.Execute(w, nil)

	} else {

		id, err := strconv.Atoi(r.FormValue("id"))
		checkError(err)
		var alUsrs model.AllUsers
		file, err := os.OpenFile("list.json", os.O_RDONLY, 0666)
		checkError(err)
		b, err := ioutil.ReadAll(file)
		checkError(err)
		json.Unmarshal(b, &alUsrs.Users)

		var allID []int
		for _, usr := range alUsrs.Users {
			allID = append(allID, usr.Id)
		}
		for _, usr := range alUsrs.Users {
			if model.IsValueInSlice(allID, id) != true {
				http.Redirect(w, r, "/showuser/notsuccededshow/", 302)
				return
			}
			if usr.Id != id {
				continue
			} else {
				t, err := template.ParseFiles("templates/showUserPage.html")
				checkError(err)
				t.Execute(w, usr)
			}

		}
	}
}

//function to handle page with successful deletion
func DeletedFunc(w http.ResponseWriter, r *http.Request) {
	http.ServeFile(w, r, "templates/deleted.html")
}

//serving file with error (add function:empty field input or uncorrect input)
func NotSucceded(w http.ResponseWriter, r *http.Request) {
	http.ServeFile(w, r, "templates/notSucceded.html")
}

//function,which serve html file,when deleting was not succesful(id input is not correct)
func NotSuccededDelete(w http.ResponseWriter, r *http.Request) {
	http.ServeFile(w, r, "templates/notSuccededDelete.html")
}

//function,which serve page with delete information input
func DeleteUserServe(w http.ResponseWriter, r *http.Request) {
	http.ServeFile(w, r, "templates/deleteUser.html")

}

//function to delete user
func DeleteUserFunc(w http.ResponseWriter, r *http.Request) {
	if r.Method == "GET" {
		t, _ := template.ParseFiles("templates/deleteUser.html")
		t.Execute(w, nil)
	} else {
		r.ParseForm()
		id, err := strconv.Atoi(r.FormValue("id"))
		checkError(err)

		//open file with users
		file, err := os.OpenFile("list.json", os.O_RDWR|os.O_APPEND, 0666)
		defer file.Close()

		//read file and unmarshall json to []users
		b, err := ioutil.ReadAll(file)
		var alUsrs model.AllUsers
		err = json.Unmarshal(b, &alUsrs.Users)
		checkError(err)

		var allID []int
		for _, usr := range alUsrs.Users {
			allID = append(allID, usr.Id)
		}
		for i, usr := range alUsrs.Users {
			if model.IsValueInSlice(allID, id) != true {
				http.Redirect(w, r, "/deleteuser/notsuccededdelete", 302)
				return
			}
			if usr.Id != id {
				continue
			} else {
				alUsrs.Users = append(alUsrs.Users[:i], alUsrs.Users[i+1:]...)
			}

		}
		newUserBytes, err := json.MarshalIndent(&alUsrs.Users, "", " ")
		checkError(err)
		ioutil.WriteFile("list.json", newUserBytes, 0666)
		http.Redirect(w, r, "/deleted", 301)
	}
}

func checkError(err error) {
	if err != nil {
		fmt.Println(err)
	}
}

//function to add user
func AddNewUserFunc(w http.ResponseWriter, r *http.Request) {

	//creating new instance and checking method
	newUser := &model.User{}
	if r.Method == "GET" {
		t, _ := template.ParseFiles("templates/addNewUser.html")
		t.Execute(w, nil)

	} else {
		resBool, errStr := checkFormValue(w, r, "firstname", "lastname")
		if resBool == false {
			t, err := template.ParseFiles("templates/notSucceded.html")
			checkError(err)
			t.Execute(w, errStr)

			return
		}
		newUser.FirstName = r.FormValue("firstname")
		newUser.LastName = r.FormValue("lastname")
		var err error
		newUser.Balance, err = strconv.ParseFloat(r.FormValue("balance"), 64)
		checkError(err)

		//open file
		file, err := os.OpenFile("list.json", os.O_RDWR, 0644)
		checkError(err)
		defer file.Close()

		//read file and unmarshall json file to slice of users
		b, err := ioutil.ReadAll(file)
		var alUsrs model.AllUsers
		err = json.Unmarshal(b, &alUsrs.Users)
		checkError(err)
		max := 0

		//generation of id(last id at the json file+1)
		for _, usr := range alUsrs.Users {
			if usr.Id > max {
				max = usr.Id
			}
		}
		id := max + 1
		newUser.Id = id

		//appending newUser to slice of all Users and rewrite json file
		alUsrs.Users = append(alUsrs.Users, newUser)
		newUserBytes, err := json.MarshalIndent(&alUsrs.Users, "", " ")
		checkError(err)
		ioutil.WriteFile("list.json", newUserBytes, 0666)
		http.Redirect(w, r, "/", 301)

	}

}

//Index page handler
func IndexFunc(w http.ResponseWriter, r *http.Request) {
	au := model.ShowAllUsers()
	t, err := template.ParseFiles("templates/indexPage.html")
	checkError(err)
	t.Execute(w, au)
}

 

示例代码:model/model.go

package model

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

func checkError(err error) {
	if err != nil {
		fmt.Println(err)
	}
}

func IsValueInSlice(slice []int, value int) (result bool) {
	for _, n := range slice {
		if n == value {
			return true
		}

	}
	return false

}

type User struct {
	Id        int     `json:"id"`
	FirstName string  `json:"firstName"`
	LastName  string  `json:"lastName"`
	Balance   float64 `json:"balance"`
}

type AllUsers struct {
	Users []*User
}

func ShowAllUsers() (au *AllUsers) {
	file, err := os.OpenFile("list.json", os.O_RDWR|os.O_APPEND, 0666)
	checkError(err)
	b, err := ioutil.ReadAll(file)
	var alUsrs AllUsers
	json.Unmarshal(b, &alUsrs.Users)
	checkError(err)
	return &alUsrs
}

 

示例代码:templates\indexPage.html

<html>
<head>
	<title>User info</title>
</head>
<body>

{{range .Users}}
<div><h3> ID:{{ .Id }} </h3></div>
<div> First Name:{{ .FirstName }}</div>
<div> Last Name:{{ .LastName }} </div>
<div> Balance:{{ .Balance }}</div>
{{end}}

<h1>Options</h1>
<form action="/addnewuser/">
    <button type="submit">Add new user</button>
</form>
<form action="/deleteuser/">
    <button type="submit">Delete user</button>
</form>
<form action="/showuser/">
    <button type="submit">Show user</button>
</form>

</body>
</html>

 

示例代码:templates\addNewUser.html

<html>
<head>
	<title>Adding new user</title>
</head>
<body>
<h2>New user's data</h2>
        <form method="POST" action="useraded">
            <label>Enter firstname</label><br>
            <input type="text" name="firstname" /><br><br>
			<label>Enter lastname</label><br>
            <input type="text" name="lastname" /><br><br>
            <label>Enter balance</label><br>
            <input type="number" name="balance" /><br><br>
            <input type="submit" value="Submit" />
        </form>
</body>
</html>

 

示例代码:templates\deleteUser.html

<html>
<head>
	<title>Delete user</title>
</head>
<body>
<h2>Please,write an id of user you want to delete</h2>
        <form method="POST" action="deleted">
            <label>Enter id</label><br>
            <input type="text" name="id" /><br><br>
            <input type="submit" value="Submit" />
        </form>
</body>
</html>

 

示例代码:templates\deleted.html

<html>
<head>
	<title>User info</title>
</head>
<body>
	<div>Done</div><br><br>
	<form action="/">
		<button type="submit">Back to main</button>
	</form>
</body>
</html>

 

示例代码:templates\notSuccededDelete.html

<html>
<head>
	<title>User info</title>
</head>
<body>
<div>There is no user with such ID</div><br><br>
<form action="/">
    <button type="submit">Back to main</button>
</form>
</body>
</html>

 

示例代码:templates\notSuccededShow.html

<html>
<head>
	<title>User info</title>
</head>
<body>
<div>Error:Cant find User with such ID,try again</div><br><br>
<form action="/">
    <button type="submit">Back to main</button>
</form>
</body>
</html>

 

示例代码:templates\showUser.html

<html>
<head>
	<title>Show user</title>
</head>
<body>
<h2>Please,write an id of user you want to show</h2>
	<form method="POST" action="show">
		<label>Enter id</label><br>
		<input type="text" name="id" /><br><br>
		<input type="submit" value="Submit" />
	</form>
</body>
</html>

 

示例代码:templates\showUserPage.html

<html>
<head>
	<title>User info</title>
</head>
<body>
	<div><h3> ID:{{.Id}} </h3></div>
	<div> First Name:{{ .FirstName }}</div>
	<div> Last Name:{{ .LastName }} </div>
	<div> Balance:{{ .Balance }}</div>
</body>
</html>

 

示例代码:templates\notSucceded.html

<html>
<head>
	<title>User info</title>
</head>
<body>
<div>Error:{{.}}</div><br><br>
<form action="/">
    <button type="submit">Back to main</button>
</form>
</body>
</html>

 

运行应用程序:

go run main.go

 

在浏览器访问http://localhost:8080即可看到如下页面

Go语言教程之边写边学:web应用:生成二维码的Web应用程序

生成条形码的算法或内部逻辑可在第三方条形码包中找到。这里的目标是展示一个示例,如何使用包并创建Web应用程序。

 

安装软件包:

go get github.com/boombuler/barcode

 

示例代码:main.go

FormValue函数将给出dataString输入字段的值,该字段将用于使用Encode函数生成QR码。

package main

import (
	"image/png"
	"net/http"
	"text/template"

	"github.com/boombuler/barcode"
	"github.com/boombuler/barcode/qr"
)

type Page struct {
	Title string
}

func main() {
	http.HandleFunc("/", homeHandler)
	http.HandleFunc("/generator/", viewCodeHandler)
	http.ListenAndServe(":8080", nil)
}

func homeHandler(w http.ResponseWriter, r *http.Request) {
	p := Page{Title: "QR Code Generator"}

	t, _ := template.ParseFiles("generator.html")
	t.Execute(w, p)
}

func viewCodeHandler(w http.ResponseWriter, r *http.Request) {
	dataString := r.FormValue("dataString")

	qrCode, _ := qr.Encode(dataString, qr.L, qr.Auto)
	qrCode, _ = barcode.Scale(qrCode, 512, 512)

	png.Encode(w, qrCode)
}

 

示例代码:generator.html

<h1>{{.Title}}</h1>
<div>Please enter the string you want to QRCode.</div>
<form action="generator/" method=post>
    <input type="text" name="dataString">
    <input type="submit" value="Submit">
</form>
Go语言教程之边写边学:web应用:获取Twitter趋势某个位置附近的热门主题标签

您想知道特定地理区域(例如加拿大、另一个国家或国家集团,甚至可能是整个世界)的Twitter趋势。Twitter的Trends API使你能够获取由Where On Earth(WOE)ID指定的地理区域的热门话题,该ID最初由Geo Planet定义,然后由Yahoo!
这是使用Twitter API获取位置附近趋势的Web应用程序的基本示例。
https://api.twitter.com/1.1/trends/place.json返回特定WOOID的前50个热门主题(如果有可用的热门信息)。与所有其他API一样,它将热门主题作为JSON数据返回,这些数据可以转换为标准Golang对象,然后使用列表推导式或类似技术进行操作。

在http://dev.twitter.com/apps的Twitter帐户下注册应用程序,并获取所需的凭据(使用者密钥、使用者密钥、访问令牌和访问令牌密钥),OAuth应用程序需要这些凭据才能获得帐户访问权限。

安装软件包:

go get github.com/dghubble/oauth1

软件包oauth1提供了OAuth 1规范的Go实现,允许最终用户授权客户端(即消费者)代表他/她访问受保护的资源。

示例代码:main.go

能够处理GET和POST请求的函数viewHashTagHandler。ParseFiles创建一个新模板,并从hash_tags.html文件中解析模板定义。

package main

import (
	"encoding/json"
	"fmt"
	"github.com/dghubble/oauth1"
	"html/template"
	"io/ioutil"
	"net/http"
	"strings"
)

func getHashTags(country string) []string {
	var listHashTags []string

	consumerKey := "xxxxxxxxxxxxxxxxxxx"
	consumerSecret := "xxxxxxxxxxxxxxxxxxx"
	accessToken := "xxxxxxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxx"
	accessSecret := "xxxxxxxxxxxxxxxxxxx"

	if consumerKey == "" || consumerSecret == "" || accessToken == "" || accessSecret == "" {
		panic("Missing required environment variable")
	}

	config := oauth1.NewConfig(consumerKey, consumerSecret)
	token := oauth1.NewToken(accessToken, accessSecret)

	httpClient := config.Client(oauth1.NoContext, token)

	path := "https://api.twitter.com/1.1/trends/place.json?id=" + country

	resp, _ := httpClient.Get(path)
	defer resp.Body.Close()
	body, _ := ioutil.ReadAll(resp.Body)

	var JSON = strings.TrimLeft(string(body), "[")
	JSON = strings.TrimRight(JSON, "]")

	var info map[string]interface{}
	json.Unmarshal([]byte(JSON), &info)
	trends := info["trends"].([]interface{})

	for _, element := range trends {
		if trendList, ok := element.(map[string]interface{}); ok {
			for key, value := range trendList {
				// Filter hashtags started with #
				if strings.Contains(key, "name") && strings.Contains(value.(string), "#") {
					listHashTags = append(listHashTags, value.(string))
				}
			}
		}
	}
	return listHashTags
}

func main() {
	http.HandleFunc("/", viewHashTagHandler)
	http.ListenAndServe(":8080", nil)
}

func viewHashTagHandler(w http.ResponseWriter, r *http.Request) {
	if r.URL.Path != "/" {
		http.Error(w, "404 not found.", http.StatusNotFound)
		return
	}

	switch r.Method {
	case "GET":
		getPage, _ := template.ParseFiles("hash_tags.html")
		getPage.Execute(w, r)
	case "POST":
		var country string
		if err := r.ParseForm(); err != nil {
			fmt.Fprintf(w, "ParseForm() err: %v", err)
			return
		}
		country = r.FormValue("country")
		tags := getHashTags(country)
		postPage, _ := template.ParseFiles("hash_tags.html")
		postPage.Execute(w, tags)
	default:
		fmt.Fprintf(w, "Unable to get result.")
	}
}

示例代码:hash_tags.html

<html>
<head>
	<title>Trending hash tags</title>
</head>
<body>
<form method="POST" action="/">
     <select name="country">
      <option value="23424848">India</option>
      <option value="455830">Brazil</option>
      <option value="3369">Canada</option>
      <option value="1">Global</option>
    </select>
    <button type="submit">Show Trends</button>
</form>

<ul>
{{ range $key, $value := . }}
   <li>{{ $value }}</li>
{{ end }}
</ul>
</body>
</html>

运行程序:

go run main.go

这将在您机器上的端口8080上的Web服务器上开发一个静态网站。这也会启动您的浏览器导航到http://localhost:8080。

Go语言教程之边写边学:web应用:如何创建照片库

照片库是一种显示保存在特定位置的不同图像的方法。在这里,不同的图像由用户上传到指定的文件夹中。为了显示图像,首先我们需要读取包含不同图像的目录,然后在读取后逐个显示图像。
 

示例代码:main.go

package main

import (
	"crypto/sha1"
	"fmt"
	"html/template"
	"io"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"strings"
)

var tpl *template.Template

func init() {
	tpl = template.Must(template.ParseGlob("templates/*"))
}

func main() {
	http.HandleFunc("/", index)
	http.Handle("/gallery/", http.StripPrefix("/gallery", http.FileServer(http.Dir("./gallery"))))
	http.Handle("/favicon.ico", http.NotFoundHandler())
	http.ListenAndServe(":8080", nil)
}

func index(w http.ResponseWriter, req *http.Request) {
	if req.Method == http.MethodPost {
		mf, fh, err := req.FormFile("nf")
		if err != nil {
			fmt.Println(err)
		}
		defer mf.Close()
		// create sha for file name
		ext := strings.Split(fh.Filename, ".")[1]
		h := sha1.New()
		io.Copy(h, mf)
		fname := fmt.Sprintf("%x", h.Sum(nil)) + "." + ext
		// create new file
		wd, err := os.Getwd()
		if err != nil {
			fmt.Println(err)
		}
		path := filepath.Join(wd, "gallery", fname)
		nf, err := os.Create(path)
		if err != nil {
			fmt.Println(err)
		}
		defer nf.Close()
		mf.Seek(0, 0)
		io.Copy(nf, mf)
	}

	file, err := os.Open("gallery")
	if err != nil {
		log.Fatalf("failed opening directory: %s", err)
	}
	defer file.Close()

	list, _ := file.Readdirnames(0) // 0 to read all files and folders
	tpl.ExecuteTemplate(w, "index.gohtml", list)
}

 

示例代码:index.html

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Image Uploader</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
  </head>
  <body>
    <div class="container">
      <h1>Photo Gallery</h1>
      <hr class="mt-2 mb-5">
      <div class="row text-center text-lg-left">
        {{range .}}
        <div class="col-lg-3 col-md-4 col-6">
          <a href="#" class="d-block mb-4 h-100">
          <img class="img-fluid img-thumbnail" src="/gallery/{{.}}">
          </a>
        </div>
        {{end}}
      </div>
      <hr class="mt-2 mb-5">
      <div class="row">
        <div class="col-lg-3 col-md-4 col-6">
          <form method="post" enctype="multipart/form-data">
            <div class="input-group">
              <div class="input-group-prepend">
                <span class="input-group-text" id="inputGroupFileAddon01">Upload</span>
              </div>
              <div class="custom-file">
                <input type="file" class="custom-file-input" name="nf" aria-describedby="inputGroupFileAddon01" id="inputGroupFile01" required> 
                <label class="custom-file-label" for="inputGroupFile01">Choose file</label>	
              </div>
            </div>
            <div class="input-group">
              <div class="custom-file">
                <input type="submit" class="btn btn-primary">
              </div>
            </div>
          </form>
        </div>
      </div>
    </div>
  </body>
</html>
Go语言教程之边写边学:常用的软件库:时间工具包

now是一个非常简单的包,它为标准时间包提供了一个方便的包装器,并使其易于处理当前时间周围的各种日期和时间构造。

 

安装软件包:

go get -u github.com/jinzhu/now

 

示例代码:

package main

import (
	"fmt"
	"time"

	"github.com/jinzhu/now"
)

func main() {
	fmt.Println("BeginningOfMinute \t", now.BeginningOfMinute())
	fmt.Println("BeginningOfHour \t", now.BeginningOfHour())
	fmt.Println("BeginningOfDay  \t", now.BeginningOfDay())
	fmt.Println("BeginningOfWeek \t", now.BeginningOfWeek())
	fmt.Println("BeginningOfMonth \t", now.BeginningOfMonth())
	fmt.Println("BeginningOfQuarter \t", now.BeginningOfQuarter())
	fmt.Println("BeginningOfYear \t", now.BeginningOfYear())
	fmt.Println()

	fmt.Println("EndOfMinute \t", now.EndOfMinute())
	fmt.Println("EndOfHour \t", now.EndOfHour())
	fmt.Println("EndOfDay  \t", now.EndOfDay())
	fmt.Println("EndOfWeek \t", now.EndOfWeek())
	fmt.Println("EndOfMonth \t", now.EndOfMonth())
	fmt.Println("EndOfQuarter \t", now.EndOfQuarter())
	fmt.Println("EndOfYear \t", now.EndOfYear())
	fmt.Println()

	fmt.Println("Monday 	\t", now.Monday())
	fmt.Println("Sunday 	\t", now.Sunday())
	fmt.Println("EndOfSunday \t", now.EndOfSunday())
	fmt.Println()

	fmt.Println(now.Parse("2017"))
	fmt.Println(now.Parse("2017-12-12 12:20"))

	t := time.Date(2020, 07, 18, 17, 51, 49, 123456789, time.Now().Location())
	fmt.Println(now.With(t).EndOfMonth())
}

 

输出:

BeginningOfMinute        2020-07-19 16:55:00 +0530 IST
BeginningOfHour          2020-07-19 16:00:00 +0530 IST
BeginningOfDay           2020-07-19 00:00:00 +0530 IST
BeginningOfWeek          2020-07-19 00:00:00 +0530 IST
BeginningOfMonth         2020-07-01 00:00:00 +0530 IST
BeginningOfQuarter       2020-07-01 00:00:00 +0530 IST
BeginningOfYear          2020-01-01 00:00:00 +0530 IST

EndOfMinute      2020-07-19 16:55:59.999999999 +0530 IST
EndOfHour        2020-07-19 16:59:59.999999999 +0530 IST
EndOfDay         2020-07-19 23:59:59.999999999 +0530 IST
EndOfWeek        2020-07-25 23:59:59.999999999 +0530 IST
EndOfMonth       2020-07-31 23:59:59.999999999 +0530 IST
EndOfQuarter     2020-09-30 23:59:59.999999999 +0530 IST
EndOfYear        2020-12-31 23:59:59.999999999 +0530 IST

Monday           2020-07-13 00:00:00 +0530 IST
Sunday           2020-07-19 00:00:00 +0530 IST
EndOfSunday      2020-07-19 23:59:59.999999999 +0530 IST

2017-01-01 00:00:00 +0530 IST 
2017-12-12 12:20:00 +0530 IST 
2020-07-31 23:59:59.999999999 +0530 IST
Go语言教程之边写边学:常用的软件库:动态XML解析器

xmlquery是用于XML文档的XPath查询包,允许您通过XPath表达式从XML文档中提取数据或计算数据。

 

安装软件包:

go get github.com/antchfx/xmlquery

示例代码:

package main

import (
	"fmt"
	"strings"

	"github.com/antchfx/xmlquery"
	"github.com/antchfx/xpath"
)

func main() {
	s := `<?xml version="1.0" encoding="UTF-8" ?>
<breakfast_menu>
	<food>
		<name price="10">Berry-Berry Belgian Waffles</name>
		<description>Light Belgian waffles</description>
		<calories>900</calories>
	</food>
	<food>
		<name price="20">French Toast</name>
		<description>Thick slices</description>
		<calories>600</calories>
	</food>
	<food>
		<name price="30">Homestyle Breakfast</name>
		<description>Two eggs, bacon or sausage</description>
		<calories>950</calories>
	</food>
</breakfast_menu>`

	doc, err := xmlquery.Parse(strings.NewReader(s))
	if err != nil {
		panic(err)
	}
	root := xmlquery.FindOne(doc, "//breakfast_menu")
	if n := root.SelectElement("//food/name"); n != nil {
		fmt.Printf("Name #%s\n", n.InnerText())
	}

	if n := root.SelectElement("//food[2]/name"); n != nil {
		fmt.Printf("Name #%s\n", n.InnerText())
	}

	for i, n := range xmlquery.Find(doc, "//food/name/@price") {
		fmt.Printf("Price #%d %s\n", i, n.InnerText())
	}

	for i, n := range xmlquery.Find(doc, "//food/calories") {
		fmt.Printf("Calories #%d %s\n", i, n.InnerText())
	}

	if n := root.SelectElement("//food[2]/name"); n != nil {
		fmt.Printf("Attr #%s\n", n.Attr)
	}

	if n := root.SelectElement("//food[2]/name"); n != nil {
		fmt.Printf("Data #%s\n", n.Data)
	}

	node := xmlquery.FindOne(doc, "//breakfast_menu/food[2]")
	if n := node.SelectElement("//description"); n != nil {
		fmt.Printf("Description #%s\n", n.InnerText())
	}

	expr, err := xpath.Compile("sum(//breakfast_menu/food/name/@price)")
	price := expr.Evaluate(xmlquery.CreateXPathNavigator(doc)).(float64)
	fmt.Printf("Total price: %f\n", price)

	countexpr, err := xpath.Compile("count(//breakfast_menu/food)")
	count := countexpr.Evaluate(xmlquery.CreateXPathNavigator(doc))
	fmt.Printf("Food Node Counts: %f\n", count)
}

 

输出:

Name #Berry-Berry Belgian Waffles
Name #French Toast
Price #0 10
Price #1 20
Price #2 30
Calories #0 900
Calories #1 600
Calories #2 950
Attr #[{{ price} 20}]
Data #name
description #Thick slices
total price: 60.000000
Food Node Counts: 3.000000
Go语言教程之边写边学:常用的软件库:图表包

go-chart是一个非常简单的golang原生图表库,支持时间序列和连续折线图。

 

安装软件包:

go get -u github.com/wcharczuk/go-chart

 

示例代码1:

package main

import (
	"os"

	"github.com/wcharczuk/go-chart"
)

func main() {
	graph := chart.BarChart{
		Title: "Test Bar Chart",
		Background: chart.Style{
			Padding: chart.Box{
				Top: 40,
			},
		},
		Height:   512,
		BarWidth: 60,
		Bars: []chart.Value{
			{Value: 5.25, Label: "Blue"},
			{Value: 4.88, Label: "Green"},
			{Value: 4.74, Label: "Gray"},
			{Value: 3.22, Label: "Orange"},
			{Value: 3, Label: "Test"},
			{Value: 2.27, Label: "??"},
			{Value: 1, Label: "!!"},
		},
	}

	f, _ := os.Create("output.png")
	defer f.Close()
	graph.Render(chart.PNG, f)
}

 

示例代码2:

package main

import (
	"os"

	"github.com/wcharczuk/go-chart"
	"github.com/wcharczuk/go-chart/drawing"
)

func main() {
	viridisByY := func(xr, yr chart.Range, index int, x, y float64) drawing.Color {
		return chart.Viridis(y, yr.GetMin(), yr.GetMax())
	}

	graph := chart.Chart{
		Series: []chart.Series{
			chart.ContinuousSeries{
				Style: chart.Style{
					StrokeWidth:      chart.Disabled,
					DotWidth:         5,
					DotColorProvider: viridisByY,
				},
				XValues: chart.Seq{Sequence: chart.NewLinearSequence().WithStart(0).WithEnd(127)}.Values(),
				YValues: chart.Seq{Sequence: chart.NewRandomSequence().WithLen(128).WithMin(0).WithMax(1024)}.Values(),
			},
		},
	}

	f, _ := os.Create("output.png")
	defer f.Close()
	graph.Render(chart.PNG, f)
}
Go语言教程之边写边学:常用的软件库:简单图像处理包

imaging包提供基本的图像处理功能(调整大小、旋转、裁剪、亮度/对比度调整等)。包提供的所有图像处理函数都接受实现图像的任何图像类型。 image接口作为输入,并返回 *image的新图像。NRGBA类型(32位RGBA颜色,非预乘alpha)。

安装软件包:

go get -u github.com/disintegration/imaging

示例代码:

package main

import (
	"image"
	"image/color"
	"log"

	"github.com/disintegration/imaging"
)

func main() {
	// 打开一个图像文件src, err := imaging.Open("test.png")
	if err != nil {
		log.Fatalf("failed to open image: %v", err)
	}

	// 从中心点裁剪300x300px
	src = imaging.CropAnchor(src, 300, 300, imaging.Center)

	// 将裁剪后的图像调整为宽度=200px,保留纵横比src = imaging.Resize(src, 200, 0, imaging.Lanczos)

	// 创建图像的模糊版本img1 := imaging.Blur(src, 5)

	// 创建具有更高对比度和清晰度的图像的灰度版本img2 := imaging.Grayscale(src)
	img2 = imaging.AdjustContrast(img2, 20)
	img2 = imaging.Sharpen(img2, 2)

	// 创建图像的反转版本img3 := imaging.Invert(src)

	// 使用卷积滤波器创建图像的浮雕版本img4 := imaging.Convolve3x3(
		src,
		[9]float64{
			-1, -1, 0,
			-1, 1, 1,
			0, 1, 1,
		},
		nil,
	)

	// 创建一个新图像,并将生成的四个图像粘贴到其中dst := imaging.New(400, 400, color.NRGBA{0, 0, 0, 0})
	dst = imaging.Paste(dst, img1, image.Pt(0, 0))
	dst = imaging.Paste(dst, img2, image.Pt(0, 200))
	dst = imaging.Paste(dst, img3, image.Pt(200, 0))
	dst = imaging.Paste(dst, img4, image.Pt(200, 200))

	// 将生成的图像另存为JPEG
	err = imaging.Save(dst, "test.jpg")
	if err != nil {
		log.Fatalf("failed to save image: %v", err)
	}
}
Go语言教程之边写边学:常用的软件库:常用正则表达式包CommonRegex

这是常用正则表达式的集合。它以简单的函数形式提供这些函数,用于获取与特定模式相对应的匹配字符串。这有助于在字符串中查找所有时间、日期、链接、电话号码、电子邮件、IP地址、价格、十六进制颜色和信用卡号。

 

安装软件包:

go get github.com/mingrammer/commonregex

 

示例代码:

package main

import (
	"fmt"

	cregex "github.com/mingrammer/commonregex"
)

func main() {
	text := `John, please get that article on www.linkedin.com 
			to me by 5:00PM on Jan 9th 2012. 4:00 would be ideal, actually. 
			If you have any questions, You can reach me at (519)-236-2723x341 or 234-567-8900 or +41 22 730 5989
			or get in touch with my associate at harold.smith@gmail.com. You system details as below:
			fe80:0:0:0:204:61ff:fe9d:f156, 192.30.253.113`

	dateList := cregex.Date(text)
	fmt.Println(dateList)

	timeList := cregex.Time(text)
	fmt.Println(timeList)

	linkList := cregex.Links(text)
	fmt.Println(linkList)

	ipList := cregex.IPs(text)
	fmt.Println(ipList)

	IPv4List := cregex.IPv4s(text)
	fmt.Println(IPv4List)

	IPv6List := cregex.IPv6s(text)
	fmt.Println(IPv6List)

	emailList := cregex.Emails(text)
	fmt.Println(emailList)

	phones := cregex.Phones(text)
	fmt.Println(phones)

	phoneList := cregex.PhonesWithExts(text)
	fmt.Println(phoneList)

	text = "price is $1,000. Pay using Credit card 4111 1111 1111 1111 and address is 504 parkwood drive, 02540, US"
	creditCard := cregex.CreditCards(text)
	fmt.Println(creditCard)
	price := cregex.Prices(text)
	fmt.Println(price)

	address := "504 parkwood drive, 02540, US"
	zip := cregex.ZipCodes(address)
	fmt.Println(zip)
	streetAddress := cregex.StreetAddresses(address)
	fmt.Println(streetAddress)
}

 

输出:

[Jan 9th 2012 2.30.253]
[5:00PM 4:00  0:20 4:61]
[www.linkedin.com harold.smith@gmail.com 192.30.253.113]
[fe80:0:0:0:204:61ff:fe9d:f156 192.30.253.113]
[192.30.253.113]
[fe80:0:0:0:204:61ff:fe9d:f156]
[harold.smith@gmail.com]
[(519)-236-2723 234-567-8900 +41 22 730 5989]
[(519)-236-2723x341]
[4111 1111 1111 1111]
[$1,000]
[02540]
[504 parkwood drive,]
Go语言教程之边写边学:常用的软件库:HTML解析器

goquery实现了类似于jQuery的功能,包括可链接的语法,用于操作和查询HTML文档。

它为Go语言带来了类似于jQuery的语法和一组功能。它基于Go的net/html包和CSS选择器库cascadia。在语法方面,它尽可能接近jQuery,尽可能使用相同的方法名称。

 

安装软件包:

go get github.com/PuerkitoBio/goquery

 

示例代码1:

package main

import (
	"fmt"
	"log"
	"net/http"

	"github.com/PuerkitoBio/goquery"
)

func ExampleScrape() {
	// http请求res, err := http.Get("https://stackoverflow.com/questions/tagged/javascript")
	if err != nil {
		log.Fatal(err)
	}
	defer res.Body.Close()
	if res.StatusCode != 200 {
		log.Fatalf("status code error: %d %s", res.StatusCode, res.Status)
	}

	// 加载html内容doc, err := goquery.NewDocumentFromReader(res.Body)
	if err != nil {
		log.Fatal(err)
	}

	// 查找目标元素doc.Find(".question-summary .summary").Each(func(i int, s *goquery.Selection) {
		title := s.Find("H3").Text()
		fmt.Println(i, title)
	})
}

func main() {
	ExampleScrape()
}

 

示例代码2:

package main

import (
	"fmt"
	"log"

	"github.com/PuerkitoBio/goquery"
)

type Earthquake struct {
	Timestamp string
	Latitide  string
	Longitude string
	Magnitudo string
	Depth     string
	Territory string
}

var arrayEarthquake []Earthquake

func postScrape() {
	doc, err := goquery.NewDocument("http://www.bmkg.go.id/gempabumi/gempabumi-terkini.bmkg")
	if err != nil {
		log.Fatal(err)
	}

	doc.Find("tbody tr").Each(func(_ int, tr *goquery.Selection) {

		e := Earthquake{}

		tr.Find("td").Each(func(ix int, td *goquery.Selection) {
			switch ix {
			case 1:
				e.Timestamp = td.Text()
			case 2:
				e.Latitide = td.Text()
			case 3:
				e.Longitude = td.Text()
			case 4:
				e.Magnitudo = td.Text()
			case 5:
				e.Depth = td.Text()
			case 6:
				e.Territory = td.Text()
			}
		})

		arrayEarthquake = append(arrayEarthquake, e)
	})

	fmt.Println(arrayEarthquake)
}

func main() {
	postScrape()
}
Go语言教程之边写边学:常用的软件库:slice和map过滤器

go-funk这个辅助函数可以解决常见问题,如删除切片中的所有重复项、获取两个集合之间的差异、用值填充数组的元素、获取两个集合之间的交集等等。

安装软件包:

go get github.com/thoas/go-funk

 

示例代码1:

package main

import (
	"fmt"

	"github.com/thoas/go-funk"
)

func main() {
	slice1 := []int{1, 3, 5, 7, 9}
	slice2 := []int{1, 2, 3, 4, 5, 6}

	// 集合1中,不包含在集合2的元素集合subtract := funk.Subtract(slice1, slice2)
	fmt.Println(subtract)

	// 计算交集intersect := funk.Intersect(slice1, slice2)
	fmt.Println(intersect)

	// 分别计算其他集合中不存在的元素slice_1_Diff, slice_2_Diff := funk.Difference(slice1, slice2)
	fmt.Println(slice_1_Diff)
	fmt.Println(slice_2_Diff)

	// 按下标打包,类似python的元组zip := funk.Zip(slice1, slice2)
	fmt.Println(zip)

	// 判断集合1是否为集合2的子集subset := funk.Subset(slice1, slice2)
	fmt.Println(subset)

	// 判断两个切片元素是否相同Equal := funk.Equal(slice1, slice2)
	fmt.Println(Equal)

	// 判断slice1是否是slice2中的一个元素convertSlice := funk.Contains(slice2, slice1)
	fmt.Println(convertSlice)
}

输出1:

[7 9]
[1 3 5]
[7 9]
[2 4 6]
[{1 1} {3 2} {5 3} {7 4} {9 5}]
false
false
false

 

示例代码2:

package main

import (
	"fmt"

	"github.com/thoas/go-funk"
)

func main() {
	var map1 = map[string]int{"Mark": 10, "Sandy": 20,
		"Rocky": 30, "Rajiv": 40, "Kate": 50}

	// 通过自定义函数转换为另一种类型flip := funk.Map(map1, func(k string, v int) (int, string) {
		return v, k
	})
	fmt.Println(flip)

	// 返回元素键数组keys := funk.Keys(map1)
	fmt.Println(keys)

	// 返回元素值数组values := funk.Values(map1)
	fmt.Println(values)
}

输出2:

map[10:Mark 20:Sandy 30:Rocky 40:Rajiv 50:Kate]
[Sandy Rocky Rajiv Kate Mark]
[40 50 10 20 30]
Go语言教程之边写边学:常用的软件库:Golang统计包

此软件包提供用于计算数值数据的数理统计的函数。即使数据集太大,也可以使用它。此包不能依赖于导入其他模块、包或库。您可以获得常用的统计函数,如平均值、中位数、标准差、方差、相关性、谐波平均值等。

安装软件包:

go get github.com/montanaflynn/stats

 

示例代码:

package main

import (
	"fmt"

	"github.com/montanaflynn/stats"
)

func main() {

	// d := stats.LoadRawData([]interface{}{1.1, "2", 3.0, 4, "5"})
	d := stats.LoadRawData([]int{1, 2, 3, 4, 5})

	a, _ := stats.Min(d)
	fmt.Println(a)
	// Output: 1.1

	a, _ = stats.Max(d)
	fmt.Println(a)
	// Output: 5

	a, _ = stats.Sum([]float64{1.1, 2.2, 3.3})
	fmt.Println(a)
	// Output: 6.6

	cs, _ := stats.CumulativeSum([]float64{1.1, 2.2, 3.3})
	fmt.Println(cs) // [1.1 3.3000000000000003 6.6]

	a, _ = stats.Mean([]float64{1, 2, 3, 4, 5})
	fmt.Println(a)
	// Output: 3

	a, _ = stats.Median([]float64{1, 2, 3, 4, 5, 6, 7})
	fmt.Println(a)
	// Output: 4

	m, _ := stats.Mode([]float64{5, 5, 3, 3, 4, 2, 1})
	fmt.Println(m)
	// Output: [5 3]

	a, _ = stats.PopulationVariance([]float64{1, 2, 3, 4, 5})
	fmt.Println(a)
	// Output: 2

	a, _ = stats.SampleVariance([]float64{1, 2, 3, 4, 5})
	fmt.Println(a)
	// Output: 2.5

	a, _ = stats.MedianAbsoluteDeviationPopulation([]float64{1, 2, 3})
	fmt.Println(a)
	// Output: 1

	a, _ = stats.StandardDeviationPopulation([]float64{1, 2, 3})
	fmt.Println(a)
	// Output: 0.816496580927726

	a, _ = stats.StandardDeviationSample([]float64{1, 2, 3})
	fmt.Println(a)
	// Output: 1

	a, _ = stats.Percentile([]float64{1, 2, 3, 4, 5}, 75)
	fmt.Println(a)
	// Output: 4

	a, _ = stats.PercentileNearestRank([]float64{35, 20, 15, 40, 50}, 75)
	fmt.Println(a)
	// Output: 40

	c := []stats.Coordinate{
		{1, 2.3},
		{2, 3.3},
		{3, 3.7},
		{4, 4.3},
		{5, 5.3},
	}

	r, _ := stats.LinearRegression(c)
	fmt.Println(r)
	// Output: [{1 2.3800000000000026} {2 3.0800000000000014} {3 3.7800000000000002} {4 4.479999999999999} {5 5.179999999999998}]

	r, _ = stats.ExponentialRegression(c)
	fmt.Println(r)
	// Output: [{1 2.5150181024736638} {2 3.032084111136781} {3 3.6554544271334493} {4 4.406984298281804} {5 5.313022222665875}]

	r, _ = stats.LogarithmicRegression(c)
	fmt.Println(r)
	// Output: [{1 2.1520822363811702} {2 3.3305559222492214} {3 4.019918836568674} {4 4.509029608117273} {5 4.888413396683663}]

	s, _ := stats.Sample([]float64{0.1, 0.2, 0.3, 0.4}, 3, false)
	fmt.Println(s)
	// Output: [0.2,0.4,0.3]

	s, _ = stats.Sample([]float64{0.1, 0.2, 0.3, 0.4}, 10, true)
	fmt.Println(s)
	// Output: [0.2,0.2,0.4,0.1,0.2,0.4,0.3,0.2,0.2,0.1]

	q, _ := stats.Quartile([]float64{7, 15, 36, 39, 40, 41})
	fmt.Println(q)
	// Output: {15 37.5 40}

	iqr, _ := stats.InterQuartileRange([]float64{102, 104, 105, 107, 108, 109, 110, 112, 115, 116, 118})
	fmt.Println(iqr)
	// Output: 10

	mh, _ := stats.Midhinge([]float64{1, 3, 4, 4, 6, 6, 6, 6, 7, 7, 7, 8, 8, 9, 9, 10, 11, 12, 13})
	fmt.Println(mh)
	// Output: 7.5

	tr, _ := stats.Trimean([]float64{1, 3, 4, 4, 6, 6, 6, 6, 7, 7, 7, 8, 8, 9, 9, 10, 11, 12, 13})
	fmt.Println(tr)
	// Output: 7.25

	o, _ := stats.QuartileOutliers([]float64{-1000, 1, 3, 4, 4, 6, 6, 6, 6, 7, 8, 15, 18, 100})
	fmt.Printf("%+v\n", o)
	// Output:  {Mild:[15 18] Extreme:[-1000 100]}

	gm, _ := stats.GeometricMean([]float64{10, 51.2, 8})
	fmt.Println(gm)
	// Output: 15.999999999999991

	hm, _ := stats.HarmonicMean([]float64{1, 2, 3, 4, 5})
	fmt.Println(hm)
	// Output: 2.18978102189781

	a, _ = stats.Round(2.18978102189781, 3)
	fmt.Println(a)
	// Output: 2.189

	e, _ := stats.ChebyshevDistance([]float64{2, 3, 4, 5, 6, 7, 8}, []float64{8, 7, 6, 5, 4, 3, 2})
	fmt.Println(e)
	// Output: 6

	e, _ = stats.ManhattanDistance([]float64{2, 3, 4, 5, 6, 7, 8}, []float64{8, 7, 6, 5, 4, 3, 2})
	fmt.Println(e)
	// Output: 24

	e, _ = stats.EuclideanDistance([]float64{2, 3, 4, 5, 6, 7, 8}, []float64{8, 7, 6, 5, 4, 3, 2})
	fmt.Println(e)
	// Output: 10.583005244258363

	e, _ = stats.MinkowskiDistance([]float64{2, 3, 4, 5, 6, 7, 8}, []float64{8, 7, 6, 5, 4, 3, 2}, float64(1))
	fmt.Println(e)
	// Output: 24

	e, _ = stats.MinkowskiDistance([]float64{2, 3, 4, 5, 6, 7, 8}, []float64{8, 7, 6, 5, 4, 3, 2}, float64(2))
	fmt.Println(e)
	// Output: 10.583005244258363

	e, _ = stats.MinkowskiDistance([]float64{2, 3, 4, 5, 6, 7, 8}, []float64{8, 7, 6, 5, 4, 3, 2}, float64(99))
	fmt.Println(e)
	// Output: 6

	cor, _ := stats.Correlation([]float64{1, 2, 3, 4, 5}, []float64{1, 2, 3, 5, 6})
	fmt.Println(cor)
	// Output: 0.9912407071619302

	ac, _ := stats.AutoCorrelation([]float64{1, 2, 3, 4, 5}, 1)
	fmt.Println(ac)
	// Output: 0.4

	sig, _ := stats.Sigmoid([]float64{3.0, 1.0, 2.1})
	fmt.Println(sig)
	// Output: [0.9525741268224334 0.7310585786300049 0.8909031788043871]

	sm, _ := stats.SoftMax([]float64{3.0, 1.0, 0.2})
	fmt.Println(sm)
	// Output: [0.8360188027814407 0.11314284146556013 0.05083835575299916]

	e, _ = stats.Entropy([]float64{1.1, 2.2, 3.3})
	fmt.Println(e)
	// Output: 1.0114042647073518
}
Go语言教程之边写边学:常用的软件库:Golang中的动态JSON

Gabs是一个小型实用程序,用于处理Go中的动态或未知JSON结构。它不需要您知道有效负载的结构(例如创建结构),并允许通过提供字段的路径来访问字段。它是一个有用的包装器,用于访问encoding/json包提供的map[string]interface{} 对象的层次结构。

安装软件包:

go get github.com/Jeffail/gabs

 

示例代码:

package main

import (
	"fmt"

	"github.com/Jeffail/gabs"
)

func main() {
	data := []byte(`{
		"employees":{
		   "protected":false,
		   "address":{
			  "street":"22 Saint-Lazare",
			  "postalCode":"75003",
			  "city":"Paris",
			  "countryCode":"FRA",
			  "country":"France"
		   },
		   "employee":[
			  {
				 "id":1,
				 "first_name":"Jeanette",
				 "last_name":"Penddreth"
			  },
			  {
				 "id":2,
				 "firstName":"Giavani",
				 "lastName":"Frediani"
			  }
		   ]
		}
	 }`)

	jsonParsed, err := gabs.ParseJSON(data)
	if err != nil {
		panic(err)
	}

	// Search JSON
	fmt.Println("Get value of Protected:\t", jsonParsed.Path("employees.protected").Data())
	fmt.Println("Get value of Country:\t", jsonParsed.Search("employees", "address", "country").Data())
	fmt.Println("ID of first employee:\t", jsonParsed.Path("employees.employee.0.id").String())
	fmt.Println("Check Country Exists:\t", jsonParsed.Exists("employees", "address", "countryCode"))

	// Iterating address objects
	for key, child := range jsonParsed.Search("employees", "address").ChildrenMap() {
		fmt.Printf("Key=>%v, Value=>%v\n", key, child.Data().(string))
	}

	// Iterating employee array
	for _, child := range jsonParsed.Search("employees", "employee").Children() {
		fmt.Println(child.Data())
	}

	// Use index in your search
	for _, child := range jsonParsed.Search("employees", "employee", "0").Children() {
		fmt.Println(child.Data())
	}
}

输出:

Get value of Protected:  false
Get value of Country:    France
ID of first employee:    1
Check Country Exists:    true
Key=>street, Value=>22 Saint-Lazare
Key=>postalCode, Value=>75003
Key=>city, Value=>Paris
Key=>countryCode, Value=>FRA
Key=>country, Value=>France
map[id:1 first_name:Jeanette last_name:Penddreth]
map[id:2 firstName:Giavani lastName:Frediani]
Jeanette
Penddreth1
Go语言教程之边写边学:常用的软件库:结构体和字段验证

包验证器根据标签对结构体和单个字段进行值验证。它具有以下独特的功能,可通过使用验证标记或自定义验证器进行跨字段和跨结构验证。切片、数组和map,允许验证多维字段的任何或所有级别。能够深入研究映射键和值以进行验证。

安装验证包:

go get github.com/go-playground/validator

 

示例代码:

package main

import (
	"fmt"

	"github.com/go-playground/validator"
)

// User contains user information
type User struct {
	FirstName   string `json:"fname" validate:"alpha"`
	LastName    string `json:"lname" validate:"alpha"`
	Age         uint8  `validate:"gte=20,lte=65"`
	Email       string `json:"e-mail" validate:"required,email"`
	JoiningDate string `validate:"datetime"`
}

// use a single instance of Validate, it caches struct info
var validate *validator.Validate

func main() {

	validate = validator.New()

	user := &User{
		FirstName:   "Test25",
		LastName:    "Test",
		Age:         75,
		Email:       "Badger.Smith@",
		JoiningDate: "005-25-10",
	}

	err := validate.Struct(user)
	if err != nil {
		if _, ok := err.(*validator.InvalidValidationError); ok {
			fmt.Println(err)
			return
		}

		fmt.Println("------ List of tag fields with error ---------")

		for _, err := range err.(validator.ValidationErrors) {
			fmt.Println(err.StructField())
			fmt.Println(err.ActualTag())
			fmt.Println(err.Kind())
			fmt.Println(err.Value())
			fmt.Println(err.Param())
			fmt.Println("---------------")
		}
		return
	}
}

 

输出:

------ List of tag fields with error ---------
FirstName
alpha
string
Test25

---------------
Age
lte
uint8
75
65
---------------
Email
email
string
Badger.Smith@

---------------
JoiningDate
datetime
string
005-25-10

---------------
  • 当前日期:
  • 北京时间:
  • 时间戳:
  • 今年的第:18周
  • 我的 IP:3.145.152.98
农历
五行
冲煞
彭祖
方位
吉神
凶神
极简任务管理 help
+ 0 0 0
Task Idea Collect