简单json使用

  1. package main
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "log"
  6. )
  7. type Movie struct {
  8. Name string `json:"name"`
  9. Year int32 `json:"year"`
  10. Actors []string
  11. }
  12. func main() {
  13. movies := []Movie{
  14. {
  15. Name: "a",
  16. Year: 2016,
  17. Actors: []string{
  18. "wht1", "wht2",
  19. },
  20. },
  21. }
  22. data, err := json.MarshalIndent(movies, "", "\t")
  23. if err != nil {
  24. log.Fatal(err)
  25. }
  26. fmt.Println(string(data))
  27. }

text/template

  1. package main
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "log"
  6. "net/http"
  7. "net/url"
  8. "os"
  9. "strings"
  10. "text/template"
  11. "time"
  12. )
  13. const IssuesURL = "https://api.github.com/search/issues"
  14. type IssuesSearchResult struct {
  15. TotalCount int `json:"total_count"`
  16. Items []*Issue
  17. }
  18. type Issue struct {
  19. Number int
  20. HTMLURL string `json:"html_url"`
  21. Title string
  22. State string
  23. User *User
  24. CreatedAt time.Time `json:"created_at"`
  25. Body string // in Markdown format
  26. }
  27. type User struct {
  28. Login string
  29. HTMLURL string `json:"html_url"`
  30. }
  31. // SearchIssues queries the GitHub issue tracker.
  32. func SearchIssues(terms []string) (*IssuesSearchResult, error) {
  33. q := url.QueryEscape(strings.Join(terms, " "))
  34. resp, err := http.Get(IssuesURL + "?q=" + q)
  35. if err != nil {
  36. return nil, err
  37. }
  38. // We must close resp.Body on all execution paths.
  39. // (Chapter 5 presents 'defer', which makes this simpler.)
  40. if resp.StatusCode != http.StatusOK {
  41. err := resp.Body.Close()
  42. if err != nil {
  43. return nil, err
  44. }
  45. return nil, fmt.Errorf("search query failed: %s", resp.Status)
  46. }
  47. var result IssuesSearchResult
  48. if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
  49. err := resp.Body.Close()
  50. if err != nil {
  51. return nil, err
  52. }
  53. return nil, err
  54. }
  55. err = resp.Body.Close()
  56. if err != nil {
  57. return nil, err
  58. }
  59. return &result, nil
  60. }
  61. func daysAgo(t time.Time) int32 {
  62. return int32(time.Since(t).Hours() / 24)
  63. }
  64. const templ = `{{.TotalCount}} issues:
  65. {{range .Items}}----------------------------------------
  66. Number: {{.Number}}
  67. User: {{.User.Login}}
  68. Title: {{.Title | printf "%.64s"}}
  69. Age: {{.CreatedAt | daysAgo}} days
  70. {{end}}`
  71. var report = template.Must(template.New("issueList").
  72. Funcs(template.FuncMap{"daysAgo": daysAgo}).Parse(templ))
  73. func main() {
  74. result, err := SearchIssues([]string{"Hello"})
  75. if err != nil {
  76. log.Fatal(err)
  77. }
  78. if err = report.Execute(os.Stdout, result); err != nil {
  79. log.Fatal(err)
  80. }
  81. }

html/template

相比于text/template,html/template会自动转义特殊字符。

  1. package main
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "html/template"
  6. "log"
  7. "net/http"
  8. "net/url"
  9. "os"
  10. "strings"
  11. "time"
  12. )
  13. const IssuesURL = "https://api.github.com/search/issues"
  14. type IssuesSearchResult struct {
  15. TotalCount int `json:"total_count"`
  16. Items []*Issue
  17. }
  18. type Issue struct {
  19. Number int
  20. HTMLURL string `json:"html_url"`
  21. Title string
  22. State string
  23. User *User
  24. CreatedAt time.Time `json:"created_at"`
  25. Body string // in Markdown format
  26. }
  27. type User struct {
  28. Login string
  29. HTMLURL string `json:"html_url"`
  30. }
  31. // SearchIssues queries the GitHub issue tracker.
  32. func SearchIssues(terms []string) (*IssuesSearchResult, error) {
  33. q := url.QueryEscape(strings.Join(terms, " "))
  34. resp, err := http.Get(IssuesURL + "?q=" + q)
  35. if err != nil {
  36. return nil, err
  37. }
  38. // We must close resp.Body on all execution paths.
  39. // (Chapter 5 presents 'defer', which makes this simpler.)
  40. if resp.StatusCode != http.StatusOK {
  41. err := resp.Body.Close()
  42. if err != nil {
  43. return nil, err
  44. }
  45. return nil, fmt.Errorf("search query failed: %s", resp.Status)
  46. }
  47. var result IssuesSearchResult
  48. if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
  49. err := resp.Body.Close()
  50. if err != nil {
  51. return nil, err
  52. }
  53. return nil, err
  54. }
  55. err = resp.Body.Close()
  56. if err != nil {
  57. return nil, err
  58. }
  59. return &result, nil
  60. }
  61. func daysAgo(t time.Time) int32 {
  62. return int32(time.Since(t).Hours() / 24)
  63. }
  64. const templ = `
  65. <h1>{{.TotalCount}} issues</h1>
  66. <table>
  67. <tr style='text-align: left'>
  68. <th>#</th>
  69. <th>State</th>
  70. <th>User</th>
  71. <th>Title</th>
  72. </tr>
  73. {{range .Items}}
  74. <tr>
  75. <td><a href='{{.HTMLURL}}'>{{.Number}}</a></td>
  76. <td>{{.State}}</td>
  77. <td><a href='{{.User.HTMLURL}}'>{{.User.Login}}</a></td>
  78. <td><a href='{{.HTMLURL}}'>{{.Title}}</a></td>
  79. </tr>
  80. {{end}}
  81. </table>
  82. `
  83. var report = template.Must(template.New("issueList").
  84. Funcs(template.FuncMap{"daysAgo": daysAgo}).Parse(templ))
  85. func main() {
  86. result, err := SearchIssues([]string{"repo:golang/go", "3133", "10535"})
  87. if err != nil {
  88. log.Fatal(err)
  89. }
  90. f, err := os.OpenFile("index.html", os.O_RDWR|os.O_CREATE, 0666)
  91. if err != nil {
  92. log.Fatal(err)
  93. }
  94. if err = report.Execute(f, result); err != nil {
  95. log.Fatal(err)
  96. }
  97. }
  1. package main
  2. import (
  3. "html/template"
  4. "log"
  5. "os"
  6. )
  7. func main() {
  8. const templ = `<p>A: {{.A}}</p><p>B: {{.B}}</p>`
  9. t := template.Must(template.New("escape").Parse(templ))
  10. var data struct {
  11. A string // untrusted plain text
  12. B template.HTML // trusted HTML
  13. }
  14. data.A = "<b>Hello!</b>"
  15. data.B = "<b>Hello!</b>"
  16. f, err := os.OpenFile("index.html", os.O_TRUNC | os.O_CREATE, 0666)
  17. if err != nil {
  18. log.Fatal(err)
  19. }
  20. if err := t.Execute(f, data); err != nil {
  21. log.Fatal(err)
  22. }
  23. }

image.png
可以看到template.HTML中的字符串不会被转义