user7857373
user7857373

Reputation:

got an error when i tried to call the value with go lang

I just starting learn this Go Lang programming, and now i'm stuck with the [] things, I tried to create a blog using the Go Lang and i'm using a template, there's no problem with the template, it just I want to append a data that I got from json file.

If I just take the data and send it through the file it's already done, but the problem is when I tried to append the slug to the data (because the json file i got no slug url in it.

That's why I want to get the title of the post then make a slug with it, then

package main

import (
    "encoding/json"
    "fmt"
    "github.com/gosimple/slug"
    "html/template"
    "io/ioutil"
    "net/http"
    "os"
)

type Blog struct {
    Title  string
    Author string
    Header string
}

type Posts struct {
    Posts []Post `json:"posts"`
}

type Post struct {
    Title       string `json:"title"`
    Author      string `json:"author"`
    Content     string `json:"content"`
    PublishDate string `json:"publishdate"`
    Image       string `json:"image"`
}

type BlogViewModel struct {
    Blog  Blog
    Posts []Post
}

func loadFile(fileName string) (string, error) {
    bytes, err := ioutil.ReadFile(fileName)

    if err != nil {
        return "", err
    }

    return string(bytes), nil
}

func loadPosts() []Post {
    jsonFile, err := os.Open("source/posts.json")
    if err != nil {
        fmt.Println(err)
    }

    fmt.Println("Successfully open the json file")
    defer jsonFile.Close()

    bytes, _ := ioutil.ReadAll(jsonFile)

    var post []Post
    json.Unmarshal(bytes, &post)

    return post
}

func handler(w http.ResponseWriter, r *http.Request) {
    blog := Blog{Title: "asd", Author: "qwe", Header: "zxc"}
    posts := loadPosts()

    viewModel := BlogViewModel{Blog: blog, Posts: posts}

    t, _ := template.ParseFiles("template/blog.html")
    t.Execute(w, viewModel)
}

The error is show in the main function

func main() {

    posts := loadPosts()

    for i := 0; i < len(posts.Post); i++ { // it gives me this error posts.Post undefined (type []Post has no field or method Post)

        fmt.Println("Title: " + posts.Post[i].Title)
    }
    // http.HandleFunc("/", handler)

    // fs := http.FileServer(http.Dir("template"))
    // http.Handle("/assets/css/", fs)
    // http.Handle("/assets/js/", fs)
    // http.Handle("/assets/fonts/", fs)
    // http.Handle("/assets/images/", fs)
    // http.Handle("/assets/media/", fs)

    // fmt.Println(http.ListenAndServe(":9000", nil))

}

I already try to solved it a couple of hours but I hit the wall, I think it's possible but I just don't find the way, I don't know what is the good keyword to solve the problem. And I don't if I already explain good enough or not. Please help me, thank you

This is the JSON file format

{
  "posts": [
    {
      "title": "sapien ut nunc",
      "author": "Jeni",
      "content": "[email protected]",
      "publishdate": "26.04.2017",
      "image": "http://dummyimage.com/188x199.png/cc0000/ffffff"
    },
    {
      "title": "mus vivamus vestibulum sagittis",
      "author": "Analise",
      "content": "[email protected]",
      "publishdate": "13.03.2017",
      "image": "http://dummyimage.com/182x113.bmp/ff4444/ffffff"
    }
  ]
}

This is the directory

Upvotes: 0

Views: 67

Answers (1)

reticentroot
reticentroot

Reputation: 3682

You're loadPost method returns []Post. Your definition of Post does not contain the attribute Post. Your Posts struct does.

Here is a modified working example. I didn't define your other structures for brevity.

package main

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

var rawJson = `{
  "posts": [
    {
      "title": "sapien ut nunc",
      "author": "Jeni",
      "content": "[email protected]",
      "publishdate": "26.04.2017",
      "image": "http://dummyimage.com/188x199.png/cc0000/ffffff"
    },
    {
      "title": "mus vivamus vestibulum sagittis",
      "author": "Analise",
      "content": "[email protected]",
      "publishdate": "13.03.2017",
      "image": "http://dummyimage.com/182x113.bmp/ff4444/ffffff"
    }
  ]
}`

type Data struct {
    Posts []struct {
        Title       string `json:"title"`
        Author      string `json:"author"`
        Content     string `json:"content"`
        Publishdate string `json:"publishdate"`
        Image       string `json:"image"`
    } `json:"posts"`
}

func loadFile(fileName string) (string, error) {
    bytes, err := ioutil.ReadFile(fileName)

    if err != nil {
        return "", err
    }
    return string(bytes), nil
}

func loadData() (Data, error) {
    var d Data
    // this is commented out so that i can load raw bytes as an example
    /*
        f, err := os.Open("source/posts.json")
        if err != nil {
            return d, err
        }
        defer f.Close()

        bytes, _ := ioutil.ReadAll(f)
    */

    // replace rawJson with bytes in prod
    json.Unmarshal([]byte(rawJson), &d)
    return d, nil
}

func main() {
    data, err := loadData()
    if err != nil {
        log.Fatal(err)
    }

    for i := 0; i < len(data.Posts); i++ {
        fmt.Println("Title: " + data.Posts[i].Title)
    }

    /*
    // you can also range over the data.Posts if you are not modifying the data then using the index is not necessary. 
    for _, post := range data.Posts {
        fmt.Println("Title: " + post.Title)
    }
    */

}

modified just for files

package main

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

type Data struct {
    Posts []struct {
        Title       string `json:"title"`
        Author      string `json:"author"`
        Content     string `json:"content"`
        Publishdate string `json:"publishdate"`
        Image       string `json:"image"`
    } `json:"posts"`
}


func loadData() (Data, error) {
    var d Data
    b, err := ioutil.ReadFile("source/posts.json")
    if err != nil {
        return d, err
    }

    err = json.Unmarshal(b, &d)
    if err != nil {
        return d, err
    }

    return d, nil
}

func main() {
    data, err := loadData()
    if err != nil {
        log.Fatal(err)
    }

    for _, post := range data.Posts {
        fmt.Println("Title: " + post.Title)
    }
}

Upvotes: 3

Related Questions