The Model in an MVC application is responsible for managing the application's data and business logic. It interacts with the database, processes data, and enforces rules and constraints.
Example: Let's consider a simple blogging platform with posts and comments.
Step-by-Step Guide:
gopackage models
type Post struct {
ID int
Title string
Content string
Author string
}
type Comment struct {
ID int
PostID int
Content string
Author string
}
For simplicity, we can use a mock in-memory database. In a real-world scenario, you would interact with a SQL or NoSQL database.
gopackage models
import (
"errors"
)
var posts = []Post{}
var comments = []Comment{}
var postIDCounter = 1
var commentIDCounter = 1
func GetAllPosts() []Post {
return posts
}
func GetPostByID(id int) (Post, error) {
for _, post := range posts {
if post.ID == id {
return post, nil
}
}
return Post{}, errors.New("post not found")
}
func CreatePost(title, content, author string) Post {
post := Post{ID: postIDCounter, Title: title, Content: content, Author: author}
postIDCounter++
posts = append(posts, post)
return post
}
func AddComment(postID int, content, author string) (Comment, error) {
post, err := GetPostByID(postID)
if err != nil {
return Comment{}, err
}
comment := Comment{ID: commentIDCounter, PostID: post.ID, Content: content, Author: author}
commentIDCounter++
comments = append(comments, comment)
return comment, nil
}
The View in an MVC application is responsible for rendering the user interface. In a web application, this typically involves generating HTML to be sent to the client.
Example:
We'll use the html/template
package to render views.
Create HTML templates for listing posts and displaying a single post with comments.
html<!-- templates/layout.html -->
<!DOCTYPE html>
<html>
<head>
<title>{{ .Title }}</title>
</head>
<body>
{{ template "content" . }}
</body>
</html>
<!-- templates/posts.html -->
{{ define "content" }}
<h1>Posts</h1>
<ul>
{{ range .Posts }}
<li><a href="/posts/{{ .ID }}">{{ .Title }}</a></li>
{{ end }}
</ul>
<a href="/posts/new">Create New Post</a>
{{ end }}
<!-- templates/post.html -->
{{ define "content" }}
<h1>{{ .Post.Title }}</h1>
<p>{{ .Post.Content }}</p>
<p>Author: {{ .Post.Author }}</p>
<h2>Comments</h2>
<ul>
{{ range .Comments }}
<li>{{ .Content }} - {{ .Author }}</li>
{{ end }}
</ul>
<a href="/posts">Back to Posts</a>
{{ end }}
Create a utility function to render templates.
gopackage views
import (
"html/template"
"net/http"
)
var templates = template.Must(template.ParseFiles("templates/layout.html", "templates/posts.html", "templates/post.html"))
func Render(w http.ResponseWriter, tmpl string, data interface{}) {
err := templates.ExecuteTemplate(w, tmpl, data)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}
The Controller in an MVC application handles user input, interacts with the Model, and selects the View to render the appropriate response.
Example: We'll create handlers for listing posts, showing a single post, and creating new posts.
gopackage controllers
import (
"net/http"
"strconv"
"example.com/mvc/models"
"example.com/mvc/views"
)
func ListPosts(w http.ResponseWriter, r *http.Request) {
posts := models.GetAllPosts()
views.Render(w, "layout.html", struct {
Title string
Posts []models.Post
}{
Title: "Posts",
Posts: posts,
})
}
func ShowPost(w http.ResponseWriter, r *http.Request) {
idStr := r.URL.Path[len("/posts/"):]
id, err := strconv.Atoi(idStr)
if err != nil {
http.NotFound(w, r)
return
}
post, err := models.GetPostByID(id)
if err != nil {
http.NotFound(w, r)
return
}
views.Render(w, "layout.html", struct {
Title string
Post models.Post
Comments []models.Comment
}{
Title: post.Title,
Post: post,
Comments: []models.Comment{}, // Fetch comments associated with the post
})
}
func CreatePost(w http.ResponseWriter, r *http.Request) {
if r.Method == http.MethodPost {
title := r.FormValue("title")
content := r.FormValue("content")
author := r.FormValue("author")
post := models.CreatePost(title, content, author)
http.Redirect(w, r, "/posts/"+strconv.Itoa(post.ID), http.StatusSeeOther)
return
}
views.Render(w, "layout.html", struct {
Title string
}{
Title: "Create New Post",
})
}
Set up routing and start the server.
gopackage main
import (
"net/http"
"example.com/mvc/controllers"
)
func main() {
http.HandleFunc("/posts", controllers.ListPosts)
http.HandleFunc("/posts/", controllers.ShowPost)
http.HandleFunc("/posts/new", controllers.CreatePost)
http.ListenAndServe(":8080", nil)
}
Implementing MVC in Go involves structuring the model to handle data and business logic, designing the view layer to render user interfaces, and writing controllers to handle user input and coordinate interactions between the model and view. This approach promotes a clean separation of concerns, making the application more modular, maintainable, and scalable.