Each microservice application will inevitably have remote calls. In JAVA, there are many methods of remote calls, the most basic handwritten HTTP call, or using restTetmplate, and then using openfeign to write only an interface.
In the Go language, Go also provides the package net/http for HTTP calls, or uses HTTP components (gentleman, grequests, heimdall, etc.) or higher-level RPC calls, as well as RPC framework (GRPC).
Then this chapter discusses how to implement HTTP call in Go language.
Interface definition
First, define the interface to facilitate subsequent remote calls.
Here, take JAVA as an example and use the most common User entity to write the corresponding operations.
For example:
GET Query list GET Query individual users POST Save user PUT Modify individual users DELETE Delete a single user
Entity class
@Data @ApiModel("User entity") @NoArgsConstructor public class User { @ApiModelProperty(notes = "User number", example = "000001") private Long id; @NotEmpty(message = "User name cannot be empty") @ApiModelProperty(notes = "user name", example = "Xiao ou") private String username; @NotEmpty(message = "Password cannot be empty") @ApiModelProperty(notes = "password", example = "123456") private String password; @NotEmpty(message = "Mobile phone number cannot be empty") @ApiModelProperty(notes = "cell-phone number", example = "110") private String telNew; @TableLogic @ApiModelProperty(notes = "Delete", example = "true") private Boolean deleted; public User(Long id, String username, String password, String telNew, Boolean deleted) { this.id = id; this.username = username; this.password = password; this.telNew = telNew; this.deleted = deleted; } }
Interface
Secondly, write the corresponding interface
@Api(tags = "user management ") @RestController @RequestMapping("user") @RequiredArgsConstructor(onConstructor_ = @Autowired) public class UserController { private final UserService userService; private final IdGen idGen; @ApiOperation("View user list") @GetMapping public Result list(@RequestParam(required = false) Integer page,@RequestParam(required = false) Integer pageSize) { Page<User> userPage = new Page<>(); userPage.setCurrent(page==null?1:page); userPage.setSize(pageSize==null?10:pageSize); Page<User> page1 = userService.page(userPage); return Result.ok("page", page1); } @ApiOperation("Get individual user information") @GetMapping("/{id}") public Result info(@PathVariable Long id) { User user = userService.getById(id); return Result.ok("user", user).put("id", id); } @ApiOperation("Save user information") @PostMapping public Result save(@RequestBody @Validated User user) { long id = idGen.nextId(); user.setId(id); boolean save = userService.save(user); return Result.ok("save", save).put("id",id); } @ApiOperation("Update user information") @PutMapping public Result update(@RequestBody @Validated User user) { boolean update = userService.updateById(user); return Result.ok("update", update); } @ApiOperation("Delete user information") @DeleteMapping("/{id}") public Result delete( @PathVariable @NotNull(message = "Cannot be empty") Long id) { boolean remove = userService.removeById(id); return Result.ok("remove", remove).put("id",id); } }
Http request call
Basic GET request
// Basic GET request func TestHttp(t *testing.T) { res, err := http.Get("http://localhost:8080/user") if err != nil { log.Fatalf("did not connect: %v", err) return } defer func(Body io.ReadCloser) { err := Body.Close() if err != nil { log.Fatalf("did not close: %v", err) return } }(res.Body) if res.StatusCode == 200 { log.Printf("success") name, err := ioutil.ReadAll(res.Body) if err != nil { log.Fatalf("could not greet: %v", err) } log.Printf("Greeting: %s", name) } }
result:
2021/09/07 18:17:38 Greeting: { "status":10020000, "resMsg":"Request succeeded", "data":{ "page":{ "records":[ { "id":1, "username":"lomtom", "password":"123345", "telNew":"110", "deleted":false },{ "id":2, "username":"side dish", "password":"123456", "telNew":"112", "deleted":false }], "total":2, "size":10, "current":1, "orders":[], "hitCount":false, "searchCount":true, "pages":1 } } }
GET request carries parameters
If you want to carry parameters after the GET request, you can choose to splice after the URL. Of course, you can also use the following methods.
// GET request carries parameters (except splicing) func TestHttp1(t *testing.T) { params := url.Values{} Url, err := url.Parse("http://localhost:8080/user") if err != nil { return } params.Set("page", "2") params.Set("pageSize", "10") Url.RawQuery = params.Encode() urlPath := Url.String() res, err := http.Get(urlPath) if err != nil { log.Fatalf("did not connect: %v", err) return } defer func(Body io.ReadCloser) { err := Body.Close() if err != nil { log.Fatalf("did not close: %v", err) return } }(res.Body) if res.StatusCode == 200 { log.Printf("success") name, err := ioutil.ReadAll(res.Body) if err != nil { log.Fatalf("could not greet: %v", err) } log.Printf("Greeting: %s", name) } }
result:
2021/09/07 18:17:38 Greeting: { "status": 10020000, "resMsg": "Request succeeded", "data": { "page": { "records": [ { "id": 1, "username": "lomtom", "password": "123345", "telNew": "110", "deleted": false }, { "id": 2, "username": "side dish", "password": "123456", "telNew": "112", "deleted": false } ], "total": 2, "size": 10, "current": 1, "orders": [], "hitCount": false, "searchCount": true, "pages": 1 } } }
Basic POST request (form)
Note: the interface acceptance type corresponding to this method must also be form acceptance, so the @ RequestBody annotation in the save method needs to be removed from the java interface, otherwise the call will fail.
// Basic POST request form func TestHttp2(t *testing.T) { params := url.Values{} params.Set("username", "Little") params.Set("password", "123456") params.Set("telNew", "112") res, err := http.PostForm("http://localhost:8080/user", params) if err != nil { log.Fatalf("did not connect: %v", err) return } defer func(Body io.ReadCloser) { err := Body.Close() if err != nil { log.Fatalf("did not close: %v", err) return } }(res.Body) if res.StatusCode == 200 { log.Printf("success") name, err := ioutil.ReadAll(res.Body) if err != nil { log.Fatalf("could not greet: %v", err) } log.Printf("Greeting: %s", name) } }
result:
2021/09/07 18:22:12 Greeting: { "status": 10020000, "resMsg": "Request succeeded", "data": { "save": true, "id": 1435186634277519360 } } 2021-09-07 18:22:12.748 DEBUG 16028 --- [nio-8080-exec-2] c.l.d.mapper.UserMapper.insert : ==> Preparing: INSERT INTO user ( id, username, password, tel_new ) VALUES ( ?, ?, ?, ? ) 2021-09-07 18:22:12.748 DEBUG 16028 --- [nio-8080-exec-2] c.l.d.mapper.UserMapper.insert : ==> Parameters: 1435186634277519360(Long), Little(String), 123456(String), 112(String) 2021-09-07 18:22:12.752 DEBUG 16028 --- [nio-8080-exec-2] c.l.d.mapper.UserMapper.insert : <== Updates: 1
POST request (body)
This method is to put the parameter in the body part of the request.
- It should also be noted that the @ RequestBody annotation in the save method should be added to the java interface, otherwise the call will fail.
- The request parameter cannot be a user-defined structure, but must be a map type. Otherwise, the interface will fail to match. It is speculated that it is related to the conversion of the user-defined structure.
- You need to set the request header parameter ResQ Header. Set("Content-Type", "application/json")
// POST request body func TestHttp3(t *testing.T) { //params := struct { // username, password, telNew string //}{"little", "123456", "112"} //str, err := json.Marshal(params) //Use structure interface mismatch params := make(map[string]interface{}) params["username"] = "Little" params["password"] = "123456" params["telNew"] = "112" str, err := json.Marshal(params) resq, err := http.NewRequest("POST","http://localhost:8080/user", bytes.NewBuffer(str)) if err != nil { log.Fatalf("error: %v", err) return } resq.Header.Set("Content-Type", "application/json") res, err := http.DefaultClient.Do(resq) if err != nil { log.Fatalf("did not connect: %v", err) return } defer func(Body io.ReadCloser) { err := Body.Close() if err != nil { log.Fatalf("did not close: %v", err) return } }(res.Body) if res.StatusCode == 200 { log.Printf("success") name, err := ioutil.ReadAll(res.Body) if err != nil { log.Fatalf("could not greet: %v", err) } log.Printf("Greeting: %s", name) } }
result:
2021/09/08 16:05:30 Greeting: { "status": 10020000, "resMsg": "Request succeeded", "data": { "save": true, "id": 1435514618490388480 } } 2021-09-08 16:05:30.857 DEBUG 6100 --- [nio-8080-exec-6] c.l.d.mapper.UserMapper.insert : ==> Preparing: INSERT INTO user ( id, username, password, tel_new ) VALUES ( ?, ?, ?, ? ) 2021-09-08 16:05:30.873 DEBUG 6100 --- [nio-8080-exec-6] c.l.d.mapper.UserMapper.insert : ==> Parameters: 1435514618490388480(Long), Little(String), 123456(String), 112(String) 2021-09-08 16:05:30.879 DEBUG 6100 --- [nio-8080-exec-6] c.l.d.mapper.UserMapper.insert : <== Updates: 1
PUT request
For net/http, two interfaces, Get and Post, are temporarily provided. For the implementation of PUT and DELETE, its advanced functions need to be used.
- First use HTTP Newrequest declares a new request and sets the corresponding request method, url, parameters, etc
- Reuse http DefaultClient. Do (ResQ) can initiate a request
// PUT request func TestHttp4(t *testing.T) { //params := struct { // id,username, password, telNew string //}{"1435514618490388480", "small", "123456", "112"} //str, err := json.Marshal(params) //Use structure interface mismatch params := make(map[string]interface{}) params["id"] = "1435514618490388480" params["username"] = "Trajectories" params["password"] = "123456" params["telNew"] = "112" str, err := json.Marshal(params) resq, err := http.NewRequest("PUT","http://localhost:8080/user", bytes.NewBuffer(str)) if err != nil { log.Fatalf("error: %v", err) return } resq.Header.Set("Content-Type", "application/json") res, err := http.DefaultClient.Do(resq) if err != nil { log.Fatalf("did not connect: %v", err) return } defer func(Body io.ReadCloser) { err := Body.Close() if err != nil { log.Fatalf("did not close: %v", err) return } }(res.Body) if res.StatusCode == 200 { log.Printf("success") name, err := ioutil.ReadAll(res.Body) if err != nil { log.Fatalf("could not greet: %v", err) } log.Printf("Greeting: %s", name) } }
result:
2021/09/08 16:09:47 Greeting: { "status": 10020000, "resMsg": "Request succeeded", "data": { "update": true } } 2021-09-08 16:14:51.785 DEBUG 4380 --- [nio-8080-exec-9] c.l.d.mapper.UserMapper.updateById : ==> Preparing: UPDATE user SET username=?, password=?, tel_new=? WHERE id=? AND deleted=0 2021-09-08 16:14:51.785 DEBUG 4380 --- [nio-8080-exec-9] c.l.d.mapper.UserMapper.updateById : ==> Parameters: Trajectories(String), 123456(String), 112(String), 1435514618490388480(Long) 2021-09-08 16:14:51.787 DEBUG 4380 --- [nio-8080-exec-9] c.l.d.mapper.UserMapper.updateById : <== Updates: 1
DELETE request
func TestHttp5(t *testing.T) { resq, err := http.NewRequest("DELETE","http://localhost:8080/user/1435514618490388480",nil) if err != nil { log.Fatalf("error: %v", err) return } res, err := http.DefaultClient.Do(resq) if err != nil { log.Fatalf("did not connect: %v", err) return } defer func(Body io.ReadCloser) { err := Body.Close() if err != nil { log.Fatalf("did not close: %v", err) return } }(res.Body) if res.StatusCode == 200 { log.Printf("success") name, err := ioutil.ReadAll(res.Body) if err != nil { log.Fatalf("could not greet: %v", err) } log.Printf("Greeting: %s", name) } }
result:
2021/09/08 16:14:14 Greeting: { "status": 10020000, "resMsg": "Request succeeded", "data": { "remove": true } } 2021-09-08 16:14:14.400 DEBUG 4380 --- [nio-8080-exec-5] c.l.d.mapper.UserMapper.deleteById : ==> Preparing: UPDATE user SET deleted=1 WHERE id=? AND deleted=0 2021-09-08 16:14:14.400 DEBUG 4380 --- [nio-8080-exec-5] c.l.d.mapper.UserMapper.deleteById : ==> Parameters: 1435514618490388480(Long) 2021-09-08 16:14:14.404 DEBUG 4380 --- [nio-8080-exec-5] c.l.d.mapper.UserMapper.deleteById : <== Updates: 1
- If you need to customize the request header and method, you can use HTTP Newrequest and HTTP DefaultClient. Do (ResQ).
- To set the header parameter, use ResQ Header. Set ("content type", "application / JSON") (refer to POST request)