为网站网站做代理被判缓刑建筑行业征信查询平台

web/2025/10/1 15:16:05/文章来源:
为网站网站做代理被判缓刑,建筑行业征信查询平台,中国最大的软件开发公司,wordpress的标签页第一部分#xff1a;构建基础命令行博客系统 代码仓库 章节 1#xff1a;Go语言快速入门 1.1 Go语言简介 Go语言#xff0c;也称作Golang#xff0c;是由Google开发的一种静态强类型、编译型语言#xff0c;具有垃圾回收功能。它在2009年公开发布#xff0c;由Robert…第一部分构建基础命令行博客系统 代码仓库 章节 1Go语言快速入门 1.1 Go语言简介 Go语言也称作Golang是由Google开发的一种静态强类型、编译型语言具有垃圾回收功能。它在2009年公开发布由Robert Griesemer、Rob Pike和Ken Thompson设计。Go语言的设计目标是为了解决大型软件系统的构建问题特别是在Google内部这些系统需要高效的编译、高效的执行以及高效的代码维护。 Go的主要特点包括 简洁、快速和安全支持并发通过goroutines和channels轻松实现丰富的标准库尤其在网络服务和并发处理方面简单的依赖管理跨平台支持多种操作系统 Go语言适用于各种类型的项目从小型个人项目到大型分布式系统。在本书中我们将使用Go语言构建一个博客系统这将帮助我们理解Go语言在实际应用中的强大功能。 1.2 安装和设置Go开发环境 让我们开始安装Go语言。请访问Go语言官方网站https://golang.org/dl/下载适合您操作系统的安装包。下载完成后请按照官方指南完成安装。 安装Go后您可以打开终端或命令提示符并运行以下命令来验证安装 go version这应该会显示安装的Go版本。例如 go version go1.15.6 linux/amd64接下来设置您的工作空间。Go语言的工作空间是存放Go代码的地方。它有一个特定的目录结构 src 目录包含Go的源文件pkg 目录包含包对象bin 目录包含可执行文件。 您可以通过设置环境变量GOPATH来指定您的工作空间目录。例如在Unix系统上 export GOPATH$HOME/go在Windows系统上 set GOPATHc:\go1.3 Hello World程序 编写Hello World程序是学习新编程语言的传统。在Go中这个程序看起来是这样的 package mainimport fmtfunc main() {fmt.Println(Hello, World!) }将上面的代码保存为hello.go。然后在命令行中运行以下命令来编译并运行程序 go run hello.go如果一切顺利您将看到终端打印出“Hello, World!”。 1.4 Go程序基本结构 Go程序由包packages组成。每个Go文件都属于一个包且文件的第一行声明了它所属的包。main包是特殊的它告诉Go编译器这个程序是可执行的而不是一个库。 在main包中main函数也是特殊的——它是程序执行的入口点。在上面的Hello World程序中我们导入了fmt 包这是一个包含I/O函数的标准库包。我们使用fmt.Println来输出字符串到标准输出。 1.5 练习编写第一个Go程序 现在是时候动手写代码了。作为练习请尝试以下操作 编写一个Go程序打印出你最喜欢的引语。修改程序接收用户输入并打印出一个个性化的问候语。 这是一个接收用户输入的示例程序 package mainimport (bufiofmtos )func main() {reader : bufio.NewReader(os.Stdin)fmt.Print(Enter your name: )name, _ : reader.ReadString(\n)fmt.Printf(Hello, %s, name) }这个程序使用bufio包创建一个新的缓冲读取器用于读取来自标准输入的数据。它提示用户输入名字然后读取输入并存储在变量name 中最后使用fmt.Printf打印个性化的问候语。 通过完成第一章读者应该能够理解Go语言的基础安装并设置好Go开发环境并编写、运行简单的Go程序。下一章将深入探讨Go语言的核心概念和功能。 章节 2Go语言基础 2.1 变量和数据类型 在Go语言中变量是存储程序执行过程中数据的容器。Go是静态类型语言这意味着变量是有明确定义的类型类型在编译时就已确定并且类型在整个程序运行期间不会改变。 声明变量 var message string message Hello, Go!// 或者一步到位 var greeting Hello, Go!// 短变量声明最常用 name : World基本数据类型 Go语言中的基本数据类型包括 整型int、uint、int8、int16、int32、int64等浮点型float32、float64布尔型bool字符串string 2.2 控制结构 控制结构在Go语言中用于控制程序的执行流程。Go提供了多种控制结构例如if语句、for循环和switch语句。 If语句 if number : 10; number%2 0 { fmt.Println(number, is even) } else { fmt.Println(number, is odd) }For循环 // 标准的for循环 for i : 0; i 5; i { fmt.Println(Value of i is:, i) }// 类似while的for循环 sum : 1 for sum 1000 { sum sum } fmt.Println(Sum is:, sum)Switch语句 dayOfWeek : 3 switch dayOfWeek { case 1: fmt.Println(Monday) case 2: fmt.Println(Tuesday) case 3: fmt.Println(Wednesday) // ... default: fmt.Println(Invalid day) }2.3 函数定义和返回值 函数是执行特定任务的代码块。在Go中您可以定义带有参数和返回值的函数。 func add(x int, y int) int { return x y }// 当连续两个或多个参数的类型相同时我们可以仅声明最后一个参数的类型 func subtract(x, y int) int { return x - y }result1 : add(6, 7) result2 : subtract(10, 3) fmt.Println(Addition result:, result1) fmt.Println(Subtraction result:, result2)2.4 错误处理基础 在Go中错误处理是通过返回一个错误类型的值来完成的。如果一个函数可能产生错误它通常是函数返回值列表中的最后一个。 func divide(x, y float64) (float64, error) { if y 0.0 { return 0.0, errors.New(cannot divide by zero) } return x / y, nil }result, err : divide(10.0, 0.0) if err ! nil { log.Fatal(err) } fmt.Println(Result:, result)2.5 练习创建基本的输入输出函数 作为练习尝试以下操作 创建一个函数接受两个字符串参数并返回它们的拼接结果。编写一个函数接受一个整数数组并返回它们的和。实现一个函数接受一个整数并返回它的阶乘。 字符串拼接函数 func concatenate(str1, str2 string) string { return str1 str2 }fmt.Println(concatenate(Hello, , Go!))整数数组求和函数 func sum(numbers []int) int { total : 0 for _, number : range numbers { total number } return total }fmt.Println(sum([]int{1, 2, 3, 4, 5}))阶乘函数 func factorial(n int) int { if n 0 { return 1 } return n * factorial(n-1) }fmt.Println(factorial(5))通过完成第二章读者应该能够理解Go语言的变量、数据类型、控制结构、函数定义以及错误处理的基础知识。这些是构建更复杂程序的基石。在下一章中我们将探索Go的标准库它提供了大量方便的工具和函数可以帮助我们更快地开发程序。 章节 3探索Go的标准库 Go的标准库是一组广泛的包提供了从输入/输出处理到网络编程的功能。在这一章节中我们将探索一些对于构建命令行博客系统非常有用的标准库包。 3.1 使用fmt包 fmt包实现了格式化的I/O函数类似于C语言的printf和scanf。我们已经在前面的Hello World程序中使用了fmt.Println来输出文本。 格式化输出 name : Go Programmer age : 30fmt.Printf(My name is %s and I am %d years old.\n, name, age)从标准输入读取 var input string fmt.Print(Enter your input: ) fmt.Scanln(input) fmt.Println(You entered:, input)3.2 文件操作io/ioutil和os包 文件操作是大多数程序中的常见任务。在Go中io/ioutil和os包提供了这方面的功能。 读取文件 content, err : ioutil.ReadFile(blogpost.txt) if err ! nil { log.Fatal(err) } fmt.Println(File content:, string(content))写入文件 message : []byte(Hello, Go Blog!) err : ioutil.WriteFile(blogpost.txt, message, 0644) if err ! nil { log.Fatal(err) }检查文件是否存在 if _, err : os.Stat(blogpost.txt); os.IsNotExist(err) { fmt.Println(The file does not exist.) } else { fmt.Println(The file exists.) }3.3 日期和时间time包 处理日期和时间是编程中的一个常见需求。Go的time包提供了这方面的功能。 获取当前时间 now : time.Now() fmt.Println(Current time:, now)格式化日期和时间 fmt.Println(Formatted time:, now.Format(2006-01-02 15:04:05))计算时间差 past : time.Date(2009, 11, 10, 23, 0, 0, 0, time.UTC) duration : now.Sub(past) fmt.Println(Duration since past:, duration)3.4 处理JSONencoding/json包 JSON是一种轻量级的数据交换格式经常被用于网络通信。在Go中encoding/json包提供了JSON数据的编码和解码功能。 JSON编码 type BlogPost struct { Title string Content string Author string Views int }post : BlogPost{ Title: Exploring Gos Standard Library, Content: Gos standard library is vast..., Author: Jane Doe, Views: 3490, }jsonBytes, err : json.Marshal(post) if err ! nil { log.Fatal(err) } fmt.Println(JSON encoding:, string(jsonBytes))JSON解码 var post BlogPost err : json.Unmarshal(jsonBytes, post) if err ! nil { log.Fatal(err) } fmt.Println(Blog post:, post)3.5 练习创建并操作自己的博客文章 作为练习尝试以下操作 创建一个结构体表示博客文章包括标题、内容、作者和发布日期。编写一个函数将博客文章结构体编码为JSON。编写另一个函数将JSON解码回博客文章结构体。将博客文章保存到文件并从文件中读取。 博客文章结构体 type BlogPost struct { Title string json:title Content string json:content Author string json:author Date time.Time json:date }编码为JSON func encodeToJSON(post BlogPost) ([]byte, error) { return json.Marshal(post) }解码JSON func decodeFromJSON(jsonBytes []byte) (BlogPost, error) { var post BlogPost err : json.Unmarshal(jsonBytes, post) return post, err }保存和读取博客文章 func savePostToFile(filename string, post BlogPost) error { jsonBytes, err : encodeToJSON(post) if err ! nil { return err } return ioutil.WriteFile(filename, jsonBytes, 0644) }func loadPostFromFile(filename string) (BlogPost, error) { jsonBytes, err : ioutil.ReadFile(filename) if err ! nil { return BlogPost{}, err } return decodeFromJSON(jsonBytes) }// 使用上述函数 post : BlogPost{ Title: My First Blog Post, Content: Content of my first blog post, Author: John Doe, Date: time.Now(), }filename : post.json// 保存博客文章到文件 err : savePostToFile(filename, post) if err ! nil { log.Fatal(err) }// 从文件中读取博客文章 loadedPost, err : loadPostFromFile(filename) if err ! nil { log.Fatal(err) } fmt.Println(Loaded blog post:, loadedPost)通过完成第三章读者应该能够理解如何使用Go的标准库来进行文件操作、日期和时间处理、以及JSON的编码和解码。这些技能对于构建命令行博客系统至关重要。在下一章中我们将学习如何使用Go的网络编程功能来让我们的博客系统可以通过网络进行数据交换。 章节 4Go的网络编程 在这一章节中我们将介绍Go语言在网络编程方面的能力。Go的net包提供了丰富的网络编程功能包括TCP/UDP协议、HTTP客户端和服务端的实现等。 4.1 创建TCP服务器 TCP传输控制协议是一种可靠的、面向连接的协议。下面的例子演示了如何创建一个简单的TCP服务器它监听本地端口并回显接收到的消息。 TCP Echo服务器 package mainimport (bufiofmtnetos )func main() {// 监听本地的12345端口listener, err : net.Listen(tcp, localhost:12345)if err ! nil {fmt.Println(Error listening:, err.Error())os.Exit(1)}defer listener.Close()fmt.Println(Listening on localhost:12345)for {// 等待连接conn, err : listener.Accept()if err ! nil {fmt.Println(Error accepting:, err.Error())os.Exit(1)}fmt.Println(Received connection)// 处理连接go handleRequest(conn)} }// 处理请求 func handleRequest(conn net.Conn) {defer conn.Close()// 创建一个新的reader从TCP连接读取数据reader : bufio.NewReader(conn)for {// 读取客户端发送的数据message, err : reader.ReadString(\n)if err ! nil {fmt.Println(Error reading:, err.Error())break}fmt.Print(Message received: , string(message))// 回显消息conn.Write([]byte(message))} }4.2 创建HTTP服务器 Go的net/http包让创建HTTP服务器变得非常简单。下面的代码展示了如何创建一个基本的HTTP服务器它可以响应GET请求。 HTTP服务器 package mainimport (fmtnet/http )func main() {// 设置路由和处理函数http.HandleFunc(/, func(w http.ResponseWriter, r *http.Request) {fmt.Fprintf(w, Welcome to the Go Blog!)})// 监听并在8080端口启动服务器fmt.Println(Server is listening on port 8080...)if err : http.ListenAndServe(:8080, nil); err ! nil {fmt.Println(Error starting server:, err)return} }4.3 创建HTTP客户端 Go的net/http包不仅可以创建服务器还可以作为客户端发送请求。以下示例展示了如何发送GET请求并读取响应。 HTTP客户端 package mainimport (fmtio/ioutilnet/http )func main() {// 向服务器发送GET请求response, err : http.Get(http://example.com)if err ! nil {fmt.Println(Error making GET request:, err)return}defer response.Body.Close()// 读取响应内容body, err : ioutil.ReadAll(response.Body)if err ! nil {fmt.Println(Error reading response:, err)return}fmt.Println(Response from server:, string(body)) }4.4 练习构建一个简单的博客服务器 作为练习尝试以下操作 创建一个HTTP服务器它可以处理不同的路由和HTTP方法。服务器应该能够响应至少两种内容静态页面和JSON响应。实现简单的文章存储功能可以通过HTTP请求添加和检索文章。 HTTP服务器处理不同路由 package mainimport (encoding/jsonfmtnet/httpsync )// BlogPost 定义了博客文章的结构 type BlogPost struct {Title string json:titleContent string json:contentAuthor string json:author }// blogPosts 存储了所有博客文章 var blogPosts make([]BlogPost, 0) var mutex sync.Mutexfunc main() {// 静态页面路由http.HandleFunc(/, func(w http.ResponseWriter, r *http.Request) {fmt.Fprintf(w, Welcome to the Go Blog!)})// 获取所有文章http.HandleFunc(/posts, func(w http.ResponseWriter, r *http.Request) {switch r.Method {case http.MethodGet:mutex.Lock()postsJSON, _ : json.Marshal(blogPosts)mutex.Unlock()w.Header().Set(Content-Type, application/json)w.Write(postsJSON)default:w.WriteHeader(http.StatusMethodNotAllowed)}})// 添加新文章http.HandleFunc(/posts/new, func(w http.ResponseWriter, r *http.Request) {switch r.Method {case http.MethodPost:var newPost BlogPosterr : json.NewDecoder(r.Body).Decode(newPost)if err ! nil {http.Error(w, err.Error(), http.StatusBadRequest)return}mutex.Lock()blogPosts append(blogPosts, newPost)mutex.Unlock()w.WriteHeader(http.StatusCreated)default:w.WriteHeader(http.StatusMethodNotAllowed)}})// 监听并在8080端口启动服务器fmt.Println(Server is listening on port 8080...)if err : http.ListenAndServe(:8080, nil); err ! nil {fmt.Println(Error starting server:, err)} }在这个例子中我们创建了一个简单的HTTP服务器它可以处理静态页面和JSON响应。我们还实现了一个简单的文章存储功能可以通过HTTP POST请求添加文章并通过HTTP GET请求检索所有文章。这个练习为创建一个更复杂和功能丰富的博客系统奠定了基础。 通过完成第四章读者应该能够理解Go语言在网络编程方面的基本概念包括创建TCP和HTTP服务器、发送HTTP请求等。这些知识对于构建网络应用程序和服务是非常重要的。在下一章中我们将学习如何将这些概念应用于我们的命令行博客系统使其能够处理网络上的博客文章。 章节 5整合网络功能到命令行博客系统 在本章中我们将把网络编程的概念整合到我们的命令行博客系统中。我们的目标是使博客系统能够通过网络接收文章并能够通过HTTP请求提供文章内容。 5.1 设计RESTful API 我们将设计一个简单的RESTful API以便于通过HTTP方法管理博客文章包括获取、创建和删除文章。 GET /posts - 获取所有文章POST /posts - 创建新文章GET /posts/{id} - 获取特定ID的文章DELETE /posts/{id} - 删除特定ID的文章 5.2 实现API服务器 我们将使用Go的net/http包来实现上述API。 服务器代码 package mainimport (encoding/jsonfmtio/ioutilnet/httpstrconvstringssync )// BlogPost 定义了博客文章的结构 type BlogPost struct {ID int json:idTitle string json:titleContent string json:contentAuthor string json:author }// blogPosts 存储了所有博客文章 var blogPosts []BlogPost var mutex sync.Mutex var idCounter intfunc main() {http.HandleFunc(/posts, postsHandler)http.HandleFunc(/posts/, postHandler)// 监听并在8080端口启动服务器fmt.Println(Server is listening on port 8080...)if err : http.ListenAndServe(:8080, nil); err ! nil {fmt.Println(Error starting server:, err)} }func postsHandler(w http.ResponseWriter, r *http.Request) {switch r.Method {case http.MethodGet:mutex.Lock()postsJSON, _ : json.Marshal(blogPosts)mutex.Unlock()w.Header().Set(Content-Type, application/json)w.Write(postsJSON)case http.MethodPost:var newPost BlogPostbodyBytes, err : ioutil.ReadAll(r.Body)if err ! nil {http.Error(w, Invalid request, http.StatusBadRequest)return}err json.Unmarshal(bodyBytes, newPost)if err ! nil {http.Error(w, Invalid JSON, http.StatusBadRequest)return}mutex.Lock()idCounternewPost.ID idCounterblogPosts append(blogPosts, newPost)mutex.Unlock()w.WriteHeader(http.StatusCreated)default:w.WriteHeader(http.StatusMethodNotAllowed)} }func postHandler(w http.ResponseWriter, r *http.Request) {idStr : strings.TrimPrefix(r.URL.Path, /posts/)id, err : strconv.Atoi(idStr)if err ! nil {http.Error(w, Invalid post ID, http.StatusBadRequest)return}switch r.Method {case http.MethodGet:found : falsefor _, post : range blogPosts {if post.ID id {postJSON, _ : json.Marshal(post)w.Header().Set(Content-Type, application/json)w.Write(postJSON)found truebreak}}if !found {http.NotFound(w, r)}case http.MethodDelete:found : falsefor i, post : range blogPosts {if post.ID id {mutex.Lock()blogPosts append(blogPosts[:i], blogPosts[i1:]...)mutex.Unlock()w.WriteHeader(http.StatusOK)found truebreak}}if !found {http.NotFound(w, r)}default:w.WriteHeader(http.StatusMethodNotAllowed)} }5.3 命令行客户端功能 我们将扩展命令行客户端以便它可以与API服务器交互获取和发布文章。 客户端代码 package mainimport (bytesencoding/jsonfmtio/ioutilnet/httpos )func main() {if len(os.Args) 2 {fmt.Println(Usage: go run blogclient.go action [params])return}switch os.Args[1] {case list:listPosts()case post:if len(os.Args) ! 5 {fmt.Println(Usage: go run blogclient.go post title content author)return}createPost(os.Args[2], os.Args[3], os.Args[4])default:fmt.Println(Unknown action)} }func listPosts() {response, err : http.Get(http://localhost:8080/posts)if err ! nil {fmt.Println(Error fetching posts:, err)return}defer response.Body.Close()body, err : ioutil.ReadAll(response.Body)if err ! nil {fmt.Println(Error reading response:, err)return}var posts []BlogPosterr json.Unmarshal(body, posts)if err ! nil {fmt.Println(Error decoding posts:, err)return}for _, post : range posts {fmt.Printf(ID: %d\nTitle: %s\nContent: %s\nAuthor: %s\n\n, post.ID, post.Title, post.Content, post.Author)} }func createPost(title, content, author string) {post : BlogPost{Title: title,Content: content,Author: author,}postJSON, err : json.Marshal(post)if err ! nil {fmt.Println(Error encoding post:, err)return}response, err : http.Post(http://localhost:8080/posts, application/json, bytes.NewBuffer(postJSON))if err ! nil {fmt.Println(Error creating post:, err)return}defer response.Body.Close()if response.StatusCode http.StatusCreated {fmt.Println(Post created successfully)} else {fmt.Printf(Failed to create post, status code: %d\n, response.StatusCode)} }5.4 练习扩展博客功能 作为练习尝试以下操作 添加命令行客户端的删除功能以便它可以通过HTTP请求删除文章。实现文章更新功能允许通过PUT请求更新现有文章的内容。添加用户认证确保只有认证用户才能创建、更新和删除文章。 添加删除功能 // 添加到 main 函数的 switch-case 中 case delete: if len(os.Args) ! 3 { fmt.Println(Usage: go run blogclient.go delete id) return } id : os.Args[2] deletePost(id) // ...func deletePost(id string) { client : http.Client{} req, err : http.NewRequest(http.MethodDelete, http://localhost:8080/posts/id, nil) if err ! nil { fmt.Println(Error creating request:, err) return }resp, err : client.Do(req) if err ! nil { fmt.Println(Error sending request:, err) return } defer resp.Body.Close()if resp.StatusCode http.StatusOK { fmt.Println(Post deleted successfully) } else { fmt.Printf(Failed to delete post, status code: %d\n, resp.StatusCode) } }实现更新功能 这需要在API服务器和客户端中添加对应的逻辑来处理PUT请求。 添加用户认证 用户认证通常涉及到更复杂的逻辑和安全性考虑例如使用JWTJSON Web Tokens或OAuth。这将超出本章的范围但是作为一个练习你可以探索如何在Go中实现这些认证机制。 通过完成第五章读者应该能够理解如何将网络编程整合到命令行博客系统中使得系统能够通过网络接收和发送数据。这些技能是构建现代网络应用程序的基础。在后续的章节中我们可以进一步探讨如何扩展系统的功能例如添加数据库支持、用户认证和更多的HTTP路由处理。 章节 6为博客系统添加持久化存储 在本章中我们将为我们的命令行博客系统添加持久化存储功能。这将允许我们的系统在服务重启后保留博客文章数据。我们将使用Go的database/sql 包来实现与SQLite数据库的交互。 6.1 设计数据库模型 我们将创建一个简单的数据库模型用于存储博客文章。 使用go mod创建项目 go mod init myblog go mod tidy项目结构 - project- db- db.go- model- models.go- api-server.go- cmd-client.go数据库模型 CREATE TABLE IF NOT EXISTS posts (idINTEGERPRIMARYKEYAUTOINCREMENT,titleTEXTNOTNULL,contentTEXTNOTNULL,authorTEXTNOTNULL );6.2 实现数据库操作 我们将实现一个简单的数据库操作层用于执行CRUD创建、读取、更新和删除操作。 数据库操作代码 package dbimport (database/sql_ github.com/mattn/go-sqlite3logmyblog/model )var db *sql.DBfunc InitDB(filePath string) {var err errordb, err sql.Open(sqlite3, filePath)if err ! nil {log.Fatal(err)}createTableSQL : CREATE TABLE IF NOT EXISTS posts (id INTEGER PRIMARY KEY AUTOINCREMENT,title TEXT NOT NULL,content TEXT NOT NULL,author TEXT NOT NULL);_, err db.Exec(createTableSQL)if err ! nil {log.Fatal(err)} }func GetPosts() ([]*model.BlogPost, error) {rows, err : db.Query(SELECT id, title, content, author FROM posts)if err ! nil {return nil, err}defer rows.Close()var posts []*model.BlogPostfor rows.Next() {var post model.BlogPostif err : rows.Scan(post.ID, post.Title, post.Content, post.Author); err ! nil {return nil, err}posts append(posts, post)}return posts, nil }func CreatePost(post model.BlogPost) (int64, error) {result, err : db.Exec(INSERT INTO posts (title, content, author) VALUES (?, ?, ?), post.Title, post.Content, post.Author)if err ! nil {return 0, err}return result.LastInsertId() }func GetPostByID(id int) (*model.BlogPost, error) {row : db.QueryRow(SELECT id, title, content, author FROM posts WHERE id ?, id)var post model.BlogPostif err : row.Scan(post.ID, post.Title, post.Content, post.Author); err ! nil {if err sql.ErrNoRows {return nil, nil}return nil, err}return post, nil }func DeletePostByID(id int) error {_, err : db.Exec(DELETE FROM posts WHERE id ?, id)return err }6.3 集成数据库操作到API服务器 我们需要修改API服务器的代码以使用数据库操作层来处理数据。 修改后的API服务器代码 // ... 保留之前的代码 ...func main() { initDB(blog.db)http.HandleFunc(/posts, postsHandler) http.HandleFunc(/posts/, postHandler)// 监听并在8080端口启动服务器 fmt.Println(Server is listening on port 8080...) if err : http.ListenAndServe(:8080, nil); err ! nil { fmt.Println(Error starting server:, err) } }func postsHandler(w http.ResponseWriter, r *http.Request) { // ... 保留之前的代码 ... case http.MethodPost: var newPost BlogPost bodyBytes, err : io.ReadAll(r.Body) if err ! nil { http.Error(w, Invalid request, http.StatusBadRequest) return } err json.Unmarshal(bodyBytes, newPost) if err ! nil { http.Error(w, Invalid JSON, http.StatusBadRequest) return }id, err : createPost(newPost) if err ! nil { http.Error(w, Error saving post, http.StatusInternalServerError) return }newPost.ID int(id) w.Header().Set(Content-Type, application/json) json.NewEncoder(w).Encode(newPost) w.WriteHeader(http.StatusCreated) default: w.WriteHeader(http.StatusMethodNotAllowed) } }// ... 修改其他处理函数以使用数据库操作 ...6.4 练习添加更新和认证功能 作为练习尝试以下操作 实现更新文章的功能允许通过PUT请求更新现有文章的内容。添加基本的用户认证确保只有认证用户才能创建、更新和删除文章。 实现更新文章功能 // 添加到数据库操作代码中 func UpdatePostByID(id int, post model.BlogPost) error { _, err : db.Exec(UPDATE posts SET title ?, content ?, author ? WHERE id ?, post.Title, post.Content, post.Author, id) return err }// 添加到API服务器中的 postHandler case http.MethodPut: var updatedPost BlogPost bodyBytes, err : ioutil.ReadAll(r.Body) if err ! nil { http.Error(w, Invalid request, http.StatusBadRequest) return } err json.Unmarshal(bodyBytes, updatedPost) if err ! nil { http.Error(w, Invalid JSON, http.StatusBadRequest) return }err updatePostByID(id, updatedPost) if err ! nil { http.Error(w, Error updating post, http.StatusInternalServerError) return }w.WriteHeader(http.StatusOK)添加用户认证功能 用户认证通常涉及到更复杂的逻辑和安全性考虑例如使用JWTJSON Web Tokens或OAuth。这将超出本章的范围但是作为一个练习你可以探索如何在Go中实现这些认证机制。 通过完成第六章读者应该能够理解如何为Go语言编写的博客系统添加持久化存储功能。我们介绍了如何使用SQLite数据库来存储数据并展示了如何将数据库操作集成到我们的API服务器中。这些知识是构建能够长期存储数据的网络应用程序的基础。在后续的章节中我们可以进一步探讨如何扩展系统的功能例如添加更复杂的数据库操作、用户认证和安全性措施。 章节 7增加用户认证和授权 在本章中我们将为我们的命令行博客系统添加用户认证和授权功能。这将确保只有经过验证的用户才能创建、更新或删除文章。我们将使用JSON Web TokensJWT来实现这一功能。 7.1 设计用户模型 首先我们需要设计一个用户模型来存储用户信息。 用户模型 CREATE TABLE IF NOT EXISTS users (idINTEGERPRIMARYKEYAUTOINCREMENT,usernameTEXTNOTNULLUNIQUE,password_hashTEXTNOTNULL );7.2 实现用户注册和登录 我们将允许用户注册和登录以便我们可以发行JWT给认证用户。 用户注册和登录代码 package mainimport (database/sqlfmtloggolang.org/x/crypto/bcryptgithub.com/dgrijalva/jwt-go )var jwtKey []byte(my_secret_key)type Claims struct {Username string json:usernamejwt.StandardClaims }// Register a new user func registerUser(username, password string) error {hashedPassword, err : bcrypt.GenerateFromPassword([]byte(password), 8)if err ! nil {return err}_, err db.Exec(INSERT INTO users (username, password_hash) VALUES (?, ?), username, hashedPassword)return err }// Authenticate a user and return a JWT func authenticateUser(username, password string) (string, error) {// Verify the username and passwordvar passwordHash stringrow : db.QueryRow(SELECT password_hash FROM users WHERE username ?, username)err : row.Scan(passwordHash)if err sql.ErrNoRows {return , fmt.Errorf(user not found)} else if err ! nil {return , err}err bcrypt.CompareHashAndPassword([]byte(passwordHash), []byte(password))if err ! nil {return , fmt.Errorf(invalid password)}// Create a new token object, specifying signing method and the claimstoken : jwt.NewWithClaims(jwt.SigningMethodHS256, Claims{Username: username,StandardClaims: jwt.StandardClaims{ExpiresAt: 15000, // Token expires in 15 seconds for demonstration purposes},})// Sign and get the complete encoded token as a string using the secrettokenString, err : token.SignedString(jwtKey)if err ! nil {return , err}return tokenString, nil }7.3 集成认证到API服务器 现在我们需要修改API服务器的代码以验证JWT并根据用户权限处理请求。 修改后的API服务器代码 // ... 保留之前的代码 ...func main() { // ... 保留之前的代码 ...http.HandleFunc(/register, registerHandler) http.HandleFunc(/login, loginHandler)// ... 保留之前的代码 ... }func registerHandler(w http.ResponseWriter, r *http.Request) { if r.Method ! http.MethodPost { w.WriteHeader(http.StatusMethodNotAllowed) return }var credentials struct { Username string json:username Password string json:password }err : json.NewDecoder(r.Body).Decode(credentials) if err ! nil { w.WriteHeader(http.StatusBadRequest) return }err registerUser(credentials.Username, credentials.Password) if err ! nil { w.WriteHeader(http.StatusInternalServerError) return }w.WriteHeader(http.StatusCreated) }func loginHandler(w http.ResponseWriter, r *http.Request) { if r.Method ! http.MethodPost { w.WriteHeader(http.StatusMethodNotAllowed) return }var credentials struct { Username string json:username Password string json:password }err : json.NewDecoder(r.Body).Decode(credentials) if err ! nil { w.WriteHeader(http.StatusBadRequest) return }tokenString, err : authenticateUser(credentials.Username, credentials.Password) if err ! nil { w.WriteHeader(http.StatusUnauthorized) return }w.Header().Set(Token, tokenString) w.WriteHeader(http.StatusOK) }// Middleware to protect private routes func authMiddleware(next http.HandlerFunc) http.HandlerFunc { return http.HandlerFunc(func (w http.ResponseWriter, r *http.Request) { tokenString : r.Header.Get(Authorization) claims : Claims{}token, err : jwt.ParseWithClaims(tokenString, claims, func (token *jwt.Token) (interface{}, error) { return jwtKey, nil })if err ! nil { if err jwt.ErrSignatureInvalid { w.WriteHeader(http.StatusUnauthorized) return } w.WriteHeader(http.StatusBadRequest) return }if !token.Valid { w.WriteHeader(http.StatusUnauthorized) return }next.ServeHTTP(w, r) }) }// ... 使用 authMiddleware 包装需要保护的路由 ...7.4 练习扩展认证功能 作为练习尝试以下操作 实现用户注销功能使得JWT在用户注销时失效。添加密码重置功能允许用户通过某种机制重置他们的密码。实现更复杂的权限系统允许不同的用户有不同的操作权限。 实现用户注销功能 用户注销功能通常涉及到使当前的JWT失效。这可以通过在服务器端维护一个失效的token列表来实现或者通过设置JWT的exp 过期时间字段为当前时间来使其立即失效。 添加密码重置功能 密码重置功能通常涉及到发送一次性链接到用户注册的电子邮件地址用户可以通过该链接来重置他们的密码。 实现更复杂的权限系统 更复杂的权限系统可能需要在用户模型中添加角色字段并在认证时检查用户角色以确定他们是否有权执行特定操作。 通过完成第七章读者应该能够理解如何在Go语言编写的博客系统中添加用户认证和授权功能。我们介绍了如何使用JWT来验证用户并保护API路由以确保只有认证用户才能执行某些操作。这些知识是构建安全网络应用程序的基础。在后续的章节中我们可以进一步探讨如何扩展系统的安全性例如通过HTTPS提供服务、实现密码策略和添加更多的安全性措施。

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

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

相关文章

老网站文章突然无收录营销网站策划

1.java关键字的使用 定义:被Java语言赋予了特殊含义,用做专门用途的字符串(单词) 特点:关键字中所字母都为小写 具体哪些关键字: 2.保留字:现Java版本尚未使用,但以后版本可能会作…

开发网站需要什么语言网站开发技术的现状及发展趋势

今天在网上看到尤雨溪推荐的这款拖拽组件,试了一下非常不错,同样推荐给大家。 VueDraggablePlus 是一个专为 Vue 打造的拖拽排序模块,基于 Sortablejs 封装,支持 Vue3 或 Vue 2.7,本月的 21 日,Vue 作者尤…

企业网站优化三层含义golang和php 做网站

在新一年的起始之际,我们很荣幸地与 Elektor 合作推出由乐鑫领衔编辑的杂志特刊。欢迎点此阅读电子版本。 Elektor 杂志作为国际电子工程和科技创新的重要平台,自 20 世纪 60 年代起,就引领着电子制造的发展潮流。如今,它已经发展…

网站建设验收确认书DANI主题wordpress

一、源码特点 PHP 药品管理系统 是一套完善的web设计系统,系统采用smarty框架进行开发设计,对理解php编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。 PHP 药店管理系统mysql数据库web结构apache计 下载地址…

网站建设公司怎样选jquery网站发展历史时间轴

时间:2009-07-06 8756次阅读【网友评论2条我要评论】收藏在使用MOS管设计开关电源或者马达驱动电路的时候,大部分人都会考虑MOS的导通电阻,最大电压等,最大电流等,也有很多人仅仅考虑这些因素。这样的电路也许是可以工…

炎陵网站建设网站开发单子

题目链接&#xff1a;http://poj.org/problem?id3041 没看题&#xff0c;网上搜最大二分匹配搜到的 匈牙利算法&#xff0c;深搜一次最多增加一个匹配 代码&#xff1a; #include <stdio.h> #include <stdlib.h> int tu[505][505]; int mx[505],my[505]; int flag…

免费样机素材网站做vi设计的国外网站

文章目录 问题描述解决方案结束语 大家好&#xff01;今天是2023年12月212日 | 农历十一月初九(距离2024年还有一周左右的时间)&#xff0c;最近还是比较忙的&#xff0c;忙着搞钱&#xff0c;毕竟马上过年啦。 问题描述 感谢大家对我一直以来的支持与帮助&#xff0c;今天这边…

贵阳市做网站电话淘宝联盟怎么推广

原文&#xff1a;https://www.freecodecamp.org/news/a-quick-intro-to-higher-order-functions-in-javascript-1a014f89c6b/译者&#xff1a;jingruzhang校对者&#xff1a;acusp高阶函数高阶函数可以接收函数作为参数&#xff0c;同时也可以返回一个新的函数。高阶函数之所以…

中国建设银行官网站电话号码室内设计效果图招聘

待总结 参考文章&#xff1a; SpringBoot 全局异常处理进阶&#xff1a;使用 ControllerAdvice 对不同的 Controller 分别捕获异常并处理 SpringBoot 对 controller 层捕获全局异常并处理的方法&#xff08;ControllerAdvice 和 ExceptionHandler&#xff09; 注解RestCont…

给网站权限做citation的网站

1. 光伏并网逆变器矢量控制 图 1 为光伏发电系统常用的逆变器拓扑结 构,太阳能光伏电池板发电所产生的直流电能接 入光伏并网逆变器直流侧。逆变器将电能逆变, 经过滤波器与隔离升压变压器连接,最终并入电 网。其中隔离变压器低压侧漏感与LC滤波器组 成LCL滤波。为便于分析…

天津环保网站建设概念做网站点击率赚钱吗

回调函数中有回调函数吗因为是我的书包&#xff0c;所以我喜欢JavaScript 。 实际上&#xff0c;我已经开始喜欢JavaScritp的面向异步回调的编程风格 。 因此&#xff0c;当我发现自己处于非JavaScript环境中时&#xff08;例如Java&#xff09; &#xff0c;我往往会错过使用回…

php网站开发都需要什么软件有风险的网站

个人使用物联卡是否合法&#xff1f;当然&#xff0c;个人是可以使用的&#xff0c;只不过是使用在除手机、平板以外的智能设备上。重点提醒&#xff1a;手机和平板除外。物联卡&#xff0c;是运营商为物流网服务企业提供的用于智能终端设备联网的&#xff0c;仅面对企业用户进…

动漫做美食的视频网站淘宝网站做超链接

最近项目中使用了wangEditor这个轻量级的富文本框&#xff0c;由于需求是一个页面中会有多个富文本框同时激活&#xff0c;所以写了个批量激活的jquery方法&#xff0c;分享一下 1 // 激活富文本框2 var wangEditorActive function(){3 var wBoxs $(".editorbox&quo…

500网站建设ADPR国际传媒网站建设

曾经想过计算机如何分析图像&#xff0c;识别并定位其中的物体吗&#xff1f;这正是计算机视觉领域的目标检测所完成的任务。DEtection TRansformer&#xff08;DETR&#xff09;和You Only Look Once&#xff08;YOLO&#xff09;是目标检测的两种重要方法。YOLO已经赢得了作为…

石家庄建设厅网站首页支付宝小程序开发费用

有点难&#x1f605; 考虑加入每一列&#xff0c;发现我们只关心当前还未确定的行的数目 有点难算&#x1f605; 设 d p i , j dp_{i,j} dpi,j​表示有 i i i列&#xff0c;其中 j j j行未确定的方案数。钦定每一列至少有一个黑色格子。 d p i , j j ( j 1 ) 2 d p i − 1…

微信微网站 留言板wordpress:代码

Go语言中的序列化技术大盘点&#xff1a;解析内建格式与主流第三方库 前言: 随着现代软件开发中的数据交互需求不断增加&#xff0c;有效地进行数据编码与序列化已成为一项关键任务。各种不同的数据格式与序列化库不仅影响着程序性能&#xff0c;也直接影响到系统的互操作性和…

织梦仿非织梦网站软件开发流程管理系统

和 equals 在 Java 中有着不同的作用和使用场景&#xff1a; 是一个操作符&#xff0c;用于比较两个对象的引用是否相同。如果两个对象引用同一个内存地址&#xff0c;则 返回 true&#xff1b;否则返回 false。在比较基本数据类型时&#xff0c; 比较的是它们的值是否相等。…

图片墙网站代码wordpress视频类模板

AR营销是新的最好的东西&#xff0c;就像元宇宙和VR营销一样。利用AR技术开展营销活动可以带来广泛的利润优势。更不用说&#xff0c;客户也喜欢AR营销&#xff01; 如果企业使用AR&#xff0c;71%的买家会更多地购物。40%的购物者准备在他们可以在AR定制的产品上花更多的钱。…

怎么重新网站做301物联网就业方向

1.img特征 2.vertical-align垂直对齐方式 与text-align对比 3.cursor指针样式 default auto pointer move text wait help 4.opacity透明度 与rgba对比 span不支持text-align属性 IE8及以下不兼容:filter:alpha(opacity0~100);

家具在线设计平台网络营销seo教程

Linux操作系统支持的函数库分为&#xff1a; 静态库&#xff0c;libxxx.a&#xff0c;在编译时就将库编译进可执行程序中。 优点&#xff1a;程序的运行环境中不需要外部的函数库。 缺点&#xff1a;可执行程序大 动态库&#xff0c;又称共享库&#xff0c;libxxx.so&#…