使用Golang的net/http包创建Web服务器

使用Golang的net/http包创建Web服务器 我们使用Go编程语言的原因之一无疑是其高性能和快速编程能力。

在本文中,我们将开发几个关于Go Web服务器的示例项目。这些示例将从简单的用法开始,然后逐步改进。

Go编程语言拥有一个优秀的包,用于开发高性能Web应用程序。这个包名为"net/http"。

阅读包文档:https://golang.org/pkg/net/http/

示例1:

在第一个示例中,我们将创建一个尽可能简单的Web服务器。该服务器将在localhost:9000上广播,然后我们将通过URI查看参数的使用。

运行以下代码:

package main
 
import (
    "fmt"
    "net/http"
)
 
func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Merhaba %s", r.URL.Path[1:])
}
 
func main() {
    http.HandleFunc("/", handler)
    http.ListenAndServe(":9000", nil)
 
    fmt.Println("Web Server")
}

这个实践的基本工作原理是什么?

首先,main()方法有两个基本代码。一个是http.HandleFunc(),另一个是ListenAndServe()。http.HandleFunc()必须有一个handler对象。这就是为什么我们使用了上面的handler()函数。当handler()执行时,它接收一个指向ResponseWriter的指针和传入的Request作为参数。我们可以从传入的HTTP请求中获取许多与HTTP相关的数据。

在这个示例中,我们只获取URI。然后我们在这个URI上做一个中断,从第一个元素开始获取后续的URI数据。这样我们将只得到URI的那部分:URI: www.xyz.com/abc

示例2:

现在,我们可以开发第二个应用程序。

图片

这个应用程序的输出将与第一个应用程序的输出相同。

示例3:

在这个示例中,我们将使用Go模板结构。首先,我们需要一个HTML模板,然后将这个HTML页面包含在应用程序中。

应用程序文件夹结构:

  • page.html
  • webServer.go

首先,我们将创建HTML页面:

图片

现在,我们可以为应用程序编写Go代码:

package main
 
import (
    "fmt"
    "io/ioutil"
    "net/http"
)
 
func loadFile(fileName string) (string, error) {
    bytes, err := ioutil.ReadFile(fileName)
    if err != nil {
        return "", err
    }
    return string(bytes), nil
}
 
func handler(w http.ResponseWriter, r *http.Request) {
    var body, _ = loadFile("page.html")
    fmt.Fprintf(w, body)
}
 
func main() {
    http.HandleFunc("/", handler)
    http.ListenAndServe(":9000", nil)
}

这个应用程序的输出将与第一个应用程序的输出相同。

示例4:

在这个应用程序中,我们将应用Go的模板模型。但这次我们还会在模板中使用Go的占位符属性。

应用程序文件夹结构:

  • page.html
  • webServer.go

现在,我们可以为应用程序编写Go代码:

图片

这个应用程序的Go代码如下:

package main
 
import (
    "bytes"
    "html/template"
    "io/ioutil"
    "net/http"
)
 
type Page struct {
    Title           string
    Author          string
    Header          string
    PageDescription string
    Content         string
    URI             string
}
 
func loadFile(fileName string) (string, error) {
    bytes, err := ioutil.ReadFile(fileName)
    if err != nil {
        return "", err
    }
    return string(bytes), nil
}
 
func handler(w http.ResponseWriter, r *http.Request) {
 
    // 字符串合并操作
    var builder bytes.Buffer
    builder.WriteString("KodLab yayınevinden çıkardığımız Yazılımcılar İçin İleri Seviye T-SQL kitabımın özellikleri aşağıdaki gibidir;\n")
    builder.WriteString("704 Sayfa\n")
    builder.WriteString("ISBN: 9.786.055.201.142\n")
    builder.WriteString("Fiyat: 37 TL\n")
    builder.WriteString("Boyut: 15 x 21\n")
    builder.WriteString("2. Baskı\n")
 
    uri := "www.cihanozhan.com/yazilimcilar-icin-ileri-seviye-t-sql-programlama-kitabi/"
 
    page := Page{
        Title:           "Kitap : İleri Seviye T-SQL Programlama",
        Author:          "Cihan Özhan",
        Header:          "İleri Seviye T-SQL Programlama",
        PageDescription: "İleri Seviye T-SQL Programlama kitap tanıtım sayfası",
        Content:         builder.String(),
        URI:             "http://" + uri}
    t, _ := template.ParseFiles("page.html")
    t.Execute(w, page)
}
 
func main() {
    http.HandleFunc("/", handler)
    http.ListenAndServe(":9000", nil)
}

示例5:

这个应用程序将是本文的最后一个应用程序。因此,我们将开发一个稍微复杂一些的应用程序。

应用程序文件夹结构:

图片

我们可以从为应用程序创建示例数据开始。为此,我们将在json文件夹下创建json文件。

users.json

[
    {
        "ID": 1,
        "Username": "CihanOzhan",
        "FirstName": "Cihan",
        "LastName": "Özhan",
        "Interest": "C#, GO, SQL Server, Oracle, Machine Learning, BigData",
        "Profile": "https://www.linkedin.com/in/cihanozhan"
    },
    {
        "ID": 2,
        "Username": "KerimFirat",
        "FirstName": "Kerim",
        "LastName": "Fırat",
        "Interest": "C, C++, Java, Linux, Android",
        "Profile": "https://www.linkedin.com/in/kerim-firat-0a3b6338"
    },
    {
        "ID": 3,
        "Username": "BarisOzhan",
        "FirstName": "Barış",
        "LastName": "Özhan",
        "Interest": "Web Tasarım, SEO, SEM",
        "Profile": "https://www.linkedin.com/in/barisozhan"
    }
]

interests.json

[
    {
        "ID": 1,
        "Name": "C#"
    },
    {
        "ID": 2,
        "Name": "GO"
    },
    {
        "ID": 3,
        "Name": "SQL Server"
    },
    {
        "ID": 4,
        "Name": "Oracle"
    },
    {
        "ID": 5,
        "Name": "BigData"
    },
    {
        "ID": 6,
        "Name": "Machine Learning"
    },
    {
        "ID": 7,
        "Name": "C"
    },
    {
        "ID": 8,
        "Name": "C++"
    },
    {
        "ID": 9,
        "Name": "Java"
    },
    {
        "ID": 10,
        "Name": "Linux"
    },
    {
        "ID": 11,
        "Name": "Android"
    },
    {
        "ID": 12,
        "Name": "Web Tasarım"
    },
    {
        "ID": 13,
        "Name": "SEO"
    },
    {
        "ID": 14,
        "Name": "SEM"
    }
]

userInterestMappings.json

[
    {
        "UserID": 1,
        "InterestID": 1
    },
    {
        "UserID": 1,
        "InterestID": 2
    },
    {
        "UserID": 1,
        "InterestID": 3
    },
    {
        "UserID": 1,
        "InterestID": 4
    },
    {
        "UserID": 1,
        "InterestID": 5
    },
    {
        "UserID": 1,
        "InterestID": 6
    },
    {
        "UserID": 2,
        "InterestID": 7
    },
    {
        "UserID": 2,
        "InterestID": 8
    },
    {
        "UserID": 2,
        "InterestID": 9
    },
    {
        "UserID": 2,
        "InterestID": 10
    },
    {
        "UserID": 2,
        "InterestID": 11
    },
    {
        "UserID": 3,
        "InterestID": 12
    },
    {
        "UserID": 3,
        "InterestID": 13
    },
    {
        "UserID": 3,
        "InterestID": 14
    }
]

现在,我们将为新应用程序创建一个page.html页面:

图片

我们几乎准备好了!现在,为了创建模型文件,我们可以进入models文件夹。

Interest.go

package models
 
type Interest struct {
    ID   int
    Name string
}

InterestMapping.go

package models
 
type InterestMapping struct {
    UserID     int
    InterestID int
}

Page.go

package models
 
type Page struct {
    ID          int
    Name        string
    Description string
    URI         string
}

User.go

package models
 
type User struct {
    ID        int
    Username  string
    FirstName string
    LastName  string
    Profile   string
    Interests []Interest
}

UserViewModel.go

package models
 
type UserViewModel struct {
    Page  Page
    Users []User
}

我们准备了应用程序的总体结构。现在,我们将编写应用程序的执行代码。

webServer.go

package main
 
import (
    "encoding/json"
    "html/template"
    "io/ioutil"
    "net/http"
 
    model "./models"
)
 
func main() {
    http.HandleFunc("/", handler)
    http.ListenAndServe(":9000", nil)
}
 
func handler(w http.ResponseWriter, r *http.Request) {
 
    page := model.Page{ID: 3, Name: "Kullanıcılar", Description: "Kullanıcı Listesi", URI: "/users"}
    users := loadUsers()
    interests := loadInterests()
    interestMappings := loadInterestMappings()
 
    var newUsers []model.User
 
    for _, user := range users {
 
        for _, interestMapping := range interestMappings {
            if user.ID == interestMapping.UserID {
                for _, interest := range interests {
                    if interestMapping.InterestID == interest.ID {
                        user.Interests = append(user.Interests, interest)
                    }
                }
            }
        }
        newUsers = append(newUsers, user)
    }
 
    viewModel := model.UserViewModel{Page: page, Users: newUsers}
 
    t, _ := template.ParseFiles("template/page.html")
    t.Execute(w, viewModel)
}
 
func loadFile(fileName string) (string, error) {
    bytes, err := ioutil.ReadFile(fileName)
    if err != nil {
        return "", err
    }
    return string(bytes), nil
}
 
func loadUsers() []model.User {
    bytes, _ := ioutil.ReadFile("json/users.json")
    var users []model.User
    json.Unmarshal(bytes, &users)
    return users
}
 
func loadInterests() []model.Interest {
    bytes, _ := ioutil.ReadFile("json/interests.json")
    var interests []model.Interest
    json.Unmarshal(bytes, &interests)
    return interests
}
 
func loadInterestMappings() []model.InterestMapping {
    bytes, _ := ioutil.ReadFile("json/userInterestMappings.json")
    var interestMappings []model.InterestMapping
    json.Unmarshal(bytes, &interestMappings)
    return interestMappings
}

当我们运行应用程序时,最终将得到以下输出:

图片

Github: https://github.com/cihanozhan/golang-webapi-samples
资源: http://www.cihanozhan.com/web-server-creation-with-golang-net-http-package/


更多关于使用Golang的net/http包创建Web服务器的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复

示例1:

在我们的第一个示例中,我们将创建一个尽可能简单的Web服务器。该服务器将在 localhost:9000 上广播。然后我们将简单地查看通过URI使用参数的方法。

你好。有两个小修正。它不会进行广播,而是在本地服务器的9000端口上进行监听

另外在第一个示例中,你在main函数末尾有一个println语句。http.ListenAndServe除非无法在指定端口上开始监听(例如端口已被占用),否则永远不会返回。所以fmt.Println(“Web Server”)只有在ListenAndServe失败时才会被调用。

更多关于使用Golang的net/http包创建Web服务器的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


以下是使用Golang的net/http包创建Web服务器的专业分析,涵盖了你提供的示例中的关键点。

示例1:基本Web服务器

在第一个示例中,代码创建了一个简单的HTTP服务器,监听端口9000。http.HandleFunc("/", handler)注册了一个处理函数,当访问根路径时,handler函数会被调用。r.URL.Path[1:]提取URI路径中第一个字符后的部分(例如,访问/hello会返回"hello")。http.ListenAndServe(":9000", nil)启动服务器并阻塞执行。

package main

import (
    "fmt"
    "net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Merhaba %s", r.URL.Path[1:])
}

func main() {
    http.HandleFunc("/", handler)
    http.ListenAndServe(":9000", nil)
}

示例2:相同输出

第二个示例与示例1输出相同,但可能通过其他方式实现,例如使用不同的处理逻辑或中间件。由于未提供代码,假设它通过类似handler函数返回相同响应。

示例3:加载HTML文件

这个示例演示了如何从文件系统加载HTML模板并作为响应返回。loadFile函数读取文件内容,handler将其写入响应。这适用于静态内容服务。

package main

import (
    "fmt"
    "io/ioutil"
    "net/http"
)

func loadFile(fileName string) (string, error) {
    bytes, err := ioutil.ReadFile(fileName)
    if err != nil {
        return "", err
    }
    return string(bytes), nil
}

func handler(w http.ResponseWriter, r *http.Request) {
    body, _ := loadFile("page.html")
    fmt.Fprintf(w, body)
}

func main() {
    http.HandleFunc("/", handler)
    http.ListenAndServe(":9000", nil)
}

示例4:使用HTML模板和数据结构

这个示例引入了Go的html/template包,通过结构体动态填充HTML模板。Page结构体定义了模板变量,template.ParseFiles解析模板文件,t.Execute(w, page)将数据渲染到响应中。

package main

import (
    "bytes"
    "html/template"
    "io/ioutil"
    "net/http"
)

type Page struct {
    Title           string
    Author          string
    Header          string
    PageDescription string
    Content         string
    URI             string
}

func loadFile(fileName string) (string, error) {
    bytes, err := ioutil.ReadFile(fileName)
    if err != nil {
        return "", err
    }
    return string(bytes), nil
}

func handler(w http.ResponseWriter, r *http.Request) {
    var builder bytes.Buffer
    builder.WriteString("KodLab yayınevinden çıkardığımız Yazılımcılar İçin İleri Seviye T-SQL kitabımın özellikleri aşağıdaki gibidir;\n")
    builder.WriteString("704 Sayfa\n")
    builder.WriteString("ISBN: 9.786.055.201.142\n")
    builder.WriteString("Fiyat: 37 TL\n")
    builder.WriteString("Boyut: 15 x 21\n")
    builder.WriteString("2. Baskı\n")

    uri := "www.cihanozhan.com/yazilimcilar-icin-ileri-seviye-t-sql-programlama-kitabi/"

    page := Page{
        Title:           "Kitap : İleri Seviye T-SQL Programlama",
        Author:          "Cihan Özhan",
        Header:          "İleri Seviye T-SQL Programlama",
        PageDescription: "İleri Seviye T-SQL Programlama kitap tanıtım sayfası",
        Content:         builder.String(),
        URI:             "http://" + uri}
    t, _ := template.ParseFiles("page.html")
    t.Execute(w, page)
}

func main() {
    http.HandleFunc("/", handler)
    http.ListenAndServe(":9000", nil)
}

示例5:复杂应用与JSON数据集成

这个示例展示了如何从JSON文件加载数据,使用模型结构体,并通过模板渲染动态内容。loadUsersloadInterestsloadInterestMappings函数读取JSON文件并解析到对应的切片中。handler函数处理数据关联(例如,将用户与兴趣映射),并使用UserViewModel传递给模板。

package main

import (
    "encoding/json"
    "html/template"
    "io/ioutil"
    "net/http"

    model "./models"
)

func main() {
    http.HandleFunc("/", handler)
    http.ListenAndServe(":9000", nil)
}

func handler(w http.ResponseWriter, r *http.Request) {
    page := model.Page{ID: 3, Name: "Kullanıcılar", Description: "Kullanıcı Listesi", URI: "/users"}
    users := loadUsers()
    interests := loadInterests()
    interestMappings := loadInterestMappings()

    var newUsers []model.User

    for _, user := range users {
        for _, interestMapping := range interestMappings {
            if user.ID == interestMapping.UserID {
                for _, interest := range interests {
                    if interestMapping.InterestID == interest.ID {
                        user.Interests = append(user.Interests, interest)
                    }
                }
            }
        }
        newUsers = append(newUsers, user)
    }

    viewModel := model.UserViewModel{Page: page, Users: newUsers}
    t, _ := template.ParseFiles("template/page.html")
    t.Execute(w, viewModel)
}

func loadFile(fileName string) (string, error) {
    bytes, err := ioutil.ReadFile(fileName)
    if err != nil {
        return "", err
    }
    return string(bytes), nil
}

func loadUsers() []model.User {
    bytes, _ := ioutil.ReadFile("json/users.json")
    var users []model.User
    json.Unmarshal(bytes, &users)
    return users
}

func loadInterests() []model.Interest {
    bytes, _ := ioutil.ReadFile("json/interests.json")
    var interests []model.Interest
    json.Unmarshal(bytes, &interests)
    return interests
}

func loadInterestMappings() []model.InterestMapping {
    bytes, _ := ioutil.ReadFile("json/userInterestMappings.json")
    var interestMappings []model.InterestMapping
    json.Unmarshal(bytes, &interestMappings)
    return interestMappings
}

这些示例覆盖了从基础到高级的Web服务器开发,包括路由、静态文件服务、模板渲染和JSON数据处理。net/http包的高性能特性使得Go适合构建高效的Web应用。

回到顶部