Skip to content

Commit 7782e53

Browse files
Add solution for gin challenge-1-basic-routing
1 parent a7ac764 commit 7782e53

File tree

1 file changed

+289
-0
lines changed
  • packages/gin/challenge-1-basic-routing/submissions/RuslanG003

1 file changed

+289
-0
lines changed
Lines changed: 289 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,289 @@
1+
package main
2+
3+
import (
4+
"errors"
5+
"net/http"
6+
"regexp"
7+
"strconv"
8+
"strings"
9+
10+
"github.com/gin-gonic/gin"
11+
)
12+
13+
// User represents a user in our system
14+
type User struct {
15+
ID int `json:"id"`
16+
Name string `json:"name"`
17+
Email string `json:"email"`
18+
Age int `json:"age"`
19+
}
20+
21+
// Response represents a standard API response
22+
type Response struct {
23+
Success bool `json:"success"`
24+
Data interface{} `json:"data,omitempty"`
25+
Message string `json:"message,omitempty"`
26+
Error string `json:"error,omitempty"`
27+
Code int `json:"code,omitempty"`
28+
}
29+
30+
// In-memory storage
31+
var users = []User{
32+
{ID: 1, Name: "John Doe", Email: "john@example.com", Age: 30},
33+
{ID: 2, Name: "Jane Smith", Email: "jane@example.com", Age: 25},
34+
{ID: 3, Name: "Bob Wilson", Email: "bob@example.com", Age: 35},
35+
}
36+
var nextID = 4
37+
38+
//main.go starts herez
39+
func main() {
40+
// TODO: Create Gin router
41+
router := gin.Default()
42+
43+
// TODO: Setup routes
44+
router.GET("/users", getAllUsers) // GET /users - Get all users
45+
router.GET("/users/:id", getUserByID) // GET /users/:id - Get user by ID
46+
router.POST("/users", createUser) // POST /users - Create new user
47+
router.PUT("/users/:id", updateUser) // PUT /users/:id - Update user
48+
router.DELETE("/users/:id", deleteUser) // DELETE /users/:id - Delete user
49+
router.GET("/users/search", searchUsers) // GET /users/search - Search users by name
50+
51+
router.Run(":8080") // TODO: Start server on http://localhost:8080
52+
}
53+
54+
// TODO: Implement handler functions
55+
56+
// getAllUsers handles GET /users
57+
func getAllUsers(c *gin.Context) {
58+
// TODO: Return all users
59+
c.JSON(http.StatusOK, Response{
60+
Success: true,
61+
Data: users,
62+
})
63+
}
64+
65+
// getUserByID handles GET /users/:id
66+
func getUserByID(c *gin.Context) {
67+
// TODO: Get user by ID
68+
userID, err := strconv.Atoi(c.Param("id"))
69+
70+
// Handle invalid ID format
71+
if err != nil {
72+
c.JSON(http.StatusBadRequest, Response{
73+
Success: false,
74+
Error: "Invalid ID format",
75+
Code: http.StatusBadRequest,
76+
})
77+
return
78+
}
79+
foundUser, index := findUserByID(userID)
80+
// Return 404 if user not found
81+
if index == -1 {
82+
c.JSON(http.StatusNotFound, Response{
83+
Success: false,
84+
Error: "404: User not found",
85+
Code: http.StatusNotFound,
86+
})
87+
return
88+
}
89+
c.JSON(http.StatusOK, Response{
90+
Success: true,
91+
Data: foundUser,
92+
})
93+
}
94+
95+
// createUser handles POST /users
96+
func createUser(c *gin.Context) {
97+
// TODO: Parse JSON request body
98+
var newUser User // Validate required fields
99+
if err := c.ShouldBindJSON(&newUser); err != nil {
100+
c.JSON(http.StatusBadRequest, Response{
101+
Success: false,
102+
Error: "Invalid JSON format",
103+
Code: http.StatusBadRequest,
104+
})
105+
return
106+
}
107+
108+
if err := validateUser(newUser); err != nil {
109+
c.JSON(http.StatusBadRequest, Response{
110+
Success: false,
111+
Error: err.Error(),
112+
Code: http.StatusBadRequest,
113+
})
114+
return
115+
}
116+
newUser.ID = nextID
117+
nextID++
118+
users = append(users, newUser) // Add user to storage
119+
// Return created user
120+
c.JSON(http.StatusCreated, Response{
121+
Success: true,
122+
Data: newUser,
123+
Message: "User creation was done",
124+
})
125+
}
126+
127+
// updateUser handles PUT /users/:id
128+
func updateUser(c *gin.Context) {
129+
// TODO: Get user ID from path
130+
userID, err := strconv.Atoi(c.Param("id"))
131+
132+
if err != nil {
133+
c.JSON(http.StatusBadRequest, Response{
134+
Success: false,
135+
Error: "Invalid user ID format",
136+
Code: http.StatusBadRequest,
137+
})
138+
return
139+
}
140+
141+
_, index := findUserByID(userID) //- так вроде правильно
142+
if index < 0 {
143+
c.JSON(http.StatusNotFound, Response{
144+
Success: false,
145+
Error: "User not found",
146+
Code: http.StatusNotFound,
147+
})
148+
return
149+
}
150+
var updatedUser User
151+
if err := c.ShouldBindJSON(&updatedUser); err != nil {
152+
c.JSON(http.StatusBadRequest, Response{
153+
Success: false,
154+
Error: "invalid JSON format",
155+
Code: http.StatusBadRequest,
156+
})
157+
return
158+
}
159+
updatedUser.ID = userID
160+
161+
if err := validateUser(updatedUser); err != nil {
162+
c.JSON(http.StatusBadRequest, Response{
163+
Success: false,
164+
Error: err.Error(),
165+
Code: http.StatusBadRequest,
166+
})
167+
return
168+
}
169+
170+
users[index] = updatedUser
171+
172+
// Parse JSON request body
173+
// Find and update user
174+
// Return updated user
175+
c.JSON(http.StatusOK, Response{
176+
Success: true,
177+
Data: updatedUser,
178+
Message: "User updated Succsesfully",
179+
})
180+
}
181+
182+
// deleteUser handles DELETE /users/:id
183+
func deleteUser(c *gin.Context) {
184+
// TODO: Get user ID from path
185+
if c == nil {
186+
c.JSON(http.StatusBadRequest, Response{
187+
Success: false,
188+
Error: "User not found",
189+
Code: http.StatusBadRequest,
190+
})
191+
return
192+
}
193+
userID, err := strconv.Atoi(c.Param("id"))
194+
195+
if err != nil {
196+
c.JSON(http.StatusBadRequest, Response{
197+
Success: false,
198+
Error: "Invalid user ID format",
199+
Code: http.StatusBadRequest,
200+
})
201+
return
202+
}
203+
204+
if userID < 0 {
205+
c.JSON(http.StatusNotFound, Response{
206+
Success: false,
207+
Error: "User not found",
208+
Code: http.StatusNotFound,
209+
})
210+
return
211+
}
212+
213+
_, index := findUserByID(userID)
214+
if index < 0 {
215+
c.JSON(http.StatusNotFound, Response{
216+
Success: false,
217+
Error: "User not found",
218+
Code: http.StatusNotFound,
219+
})
220+
return
221+
}
222+
// Find and remove user
223+
// Return success message
224+
users = append(users[:index], users[index+1:]...)
225+
c.JSON(http.StatusOK, Response{
226+
Success: true,
227+
Message: "User deleted Succsesfully",
228+
})
229+
}
230+
231+
// searchUsers handles GET /users/search?name=value
232+
func searchUsers(c *gin.Context) {
233+
// TODO: Get name query parameter
234+
nameQuery := c.Query("name")
235+
if nameQuery == "" {
236+
c.JSON(http.StatusBadRequest, Response{
237+
Success: false,
238+
Error: "Missing 'name' query parameter",
239+
Code: http.StatusBadRequest,
240+
})
241+
return
242+
}
243+
var matchedUsers []User
244+
for _, u := range users {
245+
if strings.Contains(strings.ToLower(u.Name), strings.ToLower(nameQuery)) {
246+
matchedUsers = append(matchedUsers, u)
247+
}
248+
}
249+
// Filter users by name (case-insensitive)
250+
if matchedUsers == nil {
251+
matchedUsers = make([]User, 0) // или []User{}
252+
}
253+
// Return matching users
254+
c.JSON(http.StatusOK, Response{
255+
Success: true,
256+
Data: matchedUsers,
257+
Message: "Search completed",
258+
Code: http.StatusOK,
259+
})
260+
}
261+
262+
// Helper function to find user by ID
263+
func findUserByID(id int) (*User, int) {
264+
// TODO: Implement user lookup
265+
for i, u := range users {
266+
if u.ID == id {
267+
return &users[i], i
268+
}
269+
}
270+
// Return user pointer and index, or nil and -1 if not found
271+
return nil, -1
272+
}
273+
274+
// Helper function to validate user data
275+
func validateUser(user User) error {
276+
// TODO: Implement validation
277+
// Check required fields: Name, Email
278+
if user.Name == "" {
279+
return errors.New("Name is required")
280+
}
281+
if user.Email == "" {
282+
return errors.New("Email is required")
283+
}
284+
if matched, _ := regexp.MatchString(`^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$`, user.Email); !matched {
285+
return errors.New("Email is invalid")
286+
}
287+
//
288+
return nil
289+
}

0 commit comments

Comments
 (0)