无法编写可以在 Golang 中的多个结构上工作的通用函数
Unable to write a generic function that can work on multiple Structs in Golang
我是 Go 的新手,正在学习接口和结构。我有 2 个结构 - ServiceSection 和 SliderSection 我正在尝试用它们中的每一个完成以下 2 个任务 -
- 获取 JSON 响应并将其解组。
- 使用结构创建 HTML 使用 "html/template"
因此,我正在尝试创建一个通用函数来执行可用于多个结构的任务。计划是再创建 5-6 个这样的结构。下面是我创建的代码-
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"html/template"
)
const (
getServicesAPI = "https://huyk1a44n6.execute-api.us-east-1.amazonaws.com/v1/services"
getSliderAPI = "https://huyk1a44n6.execute-api.us-east-1.amazonaws.com/v1/home-slider"
servicesTemplate = `<div class="container">
<div class="row">
<div class="col-md-12">
<div class="section-title">
<h5>{{.Heading1}}</h5>
<h2>{{.Heading2}}</h2>
</div>
</div>
</div>
<div class="row">
{{range .Services}}
<div class="col-lg-4 col-md-6">
<a class="single-services-box" href="{{.Href}}">
<div class="services-img">
<img alt="Service Images"
src="{{.Image}}">
</div>
<h3>{{.Heading}}</h3>
</a>
</div>
{{end}}
</div>
</div>`
sliderTemplate = ` {{range .Slider}}
<div class="home-slider flickity-dots-absolute" data-flickity='{ "bgLazyLoad": 1, "bgLazyLoad": true, "fade": true, "prevNextButtons": false, "autoPlay": 7000, "pauseAutoPlayOnHover": false }'>
<div class="home-slider-single-item" data-flickity-bg-lazyload="{{.Image}}">
<div class="container">
<div class="row d-flex align-items-center">
<div class="col">
<div class="home-slider-content">
<h1 class="home-slider-title">{{.title}}</h1>
<div class="home-slider-description">
<p>{{.description}}</p>
</div>
<div class="home-slider-btn-box">
<a class="button home-btn-1 mr-15" href="{{.button1_href}}">{{.button1_title}}</a>
<a class="button btn-primary" href="{{.button2_href}}">{{.button1_title}}</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{{end}}
`
)
type ServiceSection struct {
Heading1 string `json:"Heading1"`
Heading2 string `json:"Heading2"`
Services []struct {
Image string `json:"Image"`
Href string `json:"Href"`
Heading string `json:"Heading"`
} `json:"Services"`
}
type SliderStruct struct {
Title string `json:"title"`
Description string `json:"description"`
Button1Title string `json:"button1_title"`
Button1Href string `json:"button1_href"`
Button2Title string `json:"button2_title"`
Button2Href string `json:"button2_href"`
Image string `json:"Image"`
}
type SliderSection struct {
Slider []SliderStruct
}
type MyInterface interface {
populateHTML(string, string)
}
func (ss ServiceSection) populateHTML(endpoint string, tmpl string) {
populateHTMLcommon(ss, endpoint, tmpl)
}
func (ss SliderSection) populateHTML(endpoint string, tmpl string) {
populateHTMLcommon(ss, endpoint, tmpl)
}
func main() {
println("WASM Go Initialized")
ServiceSec := ServiceSection{}
SliderSec := SliderSection{}
ServiceSec.populateHTML(getServicesAPI, servicesTemplate)
SliderSec.populateHTML(getSliderAPI, sliderTemplate)
}
func populateHTMLcommon(hs MyInterface, endpoint string, tmplStr string) {
fmt.Println("struct ServiceSection", hs, endpoint)
// GET API CALL
fmt.Println("Inside getDataFromAPI()")
response, err := http.Get(endpoint)
if err != nil {
log.Fatal(err)
}
responseData, err := ioutil.ReadAll(response.Body)
if err != nil {
log.Fatal(err)
}
err = json.Unmarshal(responseData, &hs)
if err != nil {
log.Fatal(err)
}
// Create HTML using template
tmpl := template.Must(template.New("table").Parse(tmplStr))
buf := new(bytes.Buffer) // Buffer created to hold the final HTML
err = tmpl.Execute(buf, responseData) // Populate the data in the HTML template
if err != nil {
log.Fatal(err)
}
tableHTMLString := buf.String()
fmt.Println("tableHTMLString: ", tableHTMLString)
}
在执行上述程序时,我在解组时 populateHTMLcommon() 函数中出现以下错误JSON -
json: cannot unmarshal object into Go value of type main.MyInterface
这意味着它无法从 MyInterface 接口中识别适当的结构。
我不明白如何创建适用于多个结构的通用函数。感谢任何帮助。
几件事:
- Go 接口是一种抽象——因此很少需要获取接口的地址
- 如果结构的方法需要更改结构的状态(并保持更改),请使用指针接收器。
所以要解决您眼前的问题:
// err = json.Unmarshal(responseData, &hs) // address of an interface usually is not what you want
err = json.Unmarshal(responseData, hs)
并更新您的方法签名以使用指针接收器:
func (ss *ServiceSection) populateHTML(endpoint string, tmpl string) {
populateHTMLcommon(ss, endpoint, tmpl)
}
func (ss *SliderSection) populateHTML(endpoint string, tmpl string) {
populateHTMLcommon(ss, endpoint, tmpl)
}
我是 Go 的新手,正在学习接口和结构。我有 2 个结构 - ServiceSection 和 SliderSection 我正在尝试用它们中的每一个完成以下 2 个任务 -
- 获取 JSON 响应并将其解组。
- 使用结构创建 HTML 使用 "html/template"
因此,我正在尝试创建一个通用函数来执行可用于多个结构的任务。计划是再创建 5-6 个这样的结构。下面是我创建的代码-
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"html/template"
)
const (
getServicesAPI = "https://huyk1a44n6.execute-api.us-east-1.amazonaws.com/v1/services"
getSliderAPI = "https://huyk1a44n6.execute-api.us-east-1.amazonaws.com/v1/home-slider"
servicesTemplate = `<div class="container">
<div class="row">
<div class="col-md-12">
<div class="section-title">
<h5>{{.Heading1}}</h5>
<h2>{{.Heading2}}</h2>
</div>
</div>
</div>
<div class="row">
{{range .Services}}
<div class="col-lg-4 col-md-6">
<a class="single-services-box" href="{{.Href}}">
<div class="services-img">
<img alt="Service Images"
src="{{.Image}}">
</div>
<h3>{{.Heading}}</h3>
</a>
</div>
{{end}}
</div>
</div>`
sliderTemplate = ` {{range .Slider}}
<div class="home-slider flickity-dots-absolute" data-flickity='{ "bgLazyLoad": 1, "bgLazyLoad": true, "fade": true, "prevNextButtons": false, "autoPlay": 7000, "pauseAutoPlayOnHover": false }'>
<div class="home-slider-single-item" data-flickity-bg-lazyload="{{.Image}}">
<div class="container">
<div class="row d-flex align-items-center">
<div class="col">
<div class="home-slider-content">
<h1 class="home-slider-title">{{.title}}</h1>
<div class="home-slider-description">
<p>{{.description}}</p>
</div>
<div class="home-slider-btn-box">
<a class="button home-btn-1 mr-15" href="{{.button1_href}}">{{.button1_title}}</a>
<a class="button btn-primary" href="{{.button2_href}}">{{.button1_title}}</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{{end}}
`
)
type ServiceSection struct {
Heading1 string `json:"Heading1"`
Heading2 string `json:"Heading2"`
Services []struct {
Image string `json:"Image"`
Href string `json:"Href"`
Heading string `json:"Heading"`
} `json:"Services"`
}
type SliderStruct struct {
Title string `json:"title"`
Description string `json:"description"`
Button1Title string `json:"button1_title"`
Button1Href string `json:"button1_href"`
Button2Title string `json:"button2_title"`
Button2Href string `json:"button2_href"`
Image string `json:"Image"`
}
type SliderSection struct {
Slider []SliderStruct
}
type MyInterface interface {
populateHTML(string, string)
}
func (ss ServiceSection) populateHTML(endpoint string, tmpl string) {
populateHTMLcommon(ss, endpoint, tmpl)
}
func (ss SliderSection) populateHTML(endpoint string, tmpl string) {
populateHTMLcommon(ss, endpoint, tmpl)
}
func main() {
println("WASM Go Initialized")
ServiceSec := ServiceSection{}
SliderSec := SliderSection{}
ServiceSec.populateHTML(getServicesAPI, servicesTemplate)
SliderSec.populateHTML(getSliderAPI, sliderTemplate)
}
func populateHTMLcommon(hs MyInterface, endpoint string, tmplStr string) {
fmt.Println("struct ServiceSection", hs, endpoint)
// GET API CALL
fmt.Println("Inside getDataFromAPI()")
response, err := http.Get(endpoint)
if err != nil {
log.Fatal(err)
}
responseData, err := ioutil.ReadAll(response.Body)
if err != nil {
log.Fatal(err)
}
err = json.Unmarshal(responseData, &hs)
if err != nil {
log.Fatal(err)
}
// Create HTML using template
tmpl := template.Must(template.New("table").Parse(tmplStr))
buf := new(bytes.Buffer) // Buffer created to hold the final HTML
err = tmpl.Execute(buf, responseData) // Populate the data in the HTML template
if err != nil {
log.Fatal(err)
}
tableHTMLString := buf.String()
fmt.Println("tableHTMLString: ", tableHTMLString)
}
在执行上述程序时,我在解组时 populateHTMLcommon() 函数中出现以下错误JSON -
json: cannot unmarshal object into Go value of type main.MyInterface
这意味着它无法从 MyInterface 接口中识别适当的结构。
我不明白如何创建适用于多个结构的通用函数。感谢任何帮助。
几件事:
- Go 接口是一种抽象——因此很少需要获取接口的地址
- 如果结构的方法需要更改结构的状态(并保持更改),请使用指针接收器。
所以要解决您眼前的问题:
// err = json.Unmarshal(responseData, &hs) // address of an interface usually is not what you want
err = json.Unmarshal(responseData, hs)
并更新您的方法签名以使用指针接收器:
func (ss *ServiceSection) populateHTML(endpoint string, tmpl string) {
populateHTMLcommon(ss, endpoint, tmpl)
}
func (ss *SliderSection) populateHTML(endpoint string, tmpl string) {
populateHTMLcommon(ss, endpoint, tmpl)
}