0

我是 Go 新手,正在学习接口和结构。我有 2 个结构 - ServiceSectionSliderSection,我正在尝试用它们完成以下 2 个任务-

  1. 获取 JSON 响应并解组它。
  2. 使用 struct 使用“html/template”创建 HTML

因此,我正在尝试创建一个通用函数来执行可用于多个结构的任务。计划是再创建 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)
        }

在执行上述程序时,我在解组 JSON 时在populateHTMLcommon()函数中收到以下错误 -

json:无法将对象解组为 main.MyInterface 类型的 Go 值

这意味着它无法从MyInterface接口识别适当的结构。

我不明白如何创建一个适用于多个结构的通用函数。任何帮助表示赞赏。

4

1 回答 1

2

有几件事:

  • 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)
}

https://play.golang.org/p/cGmm3Cs5XTk

于 2021-06-01T12:22:49.597 回答