I have some code that makes 3 requests to fill 3 variables now. Two requests are same. I want to share one http request between two different functions (in real world, these functions are splitted into two different modules).
Let me describe the problem what I have based on much simpler example than I have in real world.
At the moment, I have the following main function and Post data structure:
type Post struct {
ID int `json:"id"`
Title string `json:"title"`
UserID int `json:"userId"`
isCompleted bool `json:"completed"`
}
func main() {
var wg sync.WaitGroup
fmt.Println("Hello, world.")
wg.Add(3)
var firstPostID int
var secondPostID int
var secondPostName string
go func() {
firstPostID = getFirstPostID()
defer wg.Done()
}()
go func() {
secondPostID = getSecondPostID()
defer wg.Done()
}()
go func() {
secondPostName = getSecondPostName()
defer wg.Done()
}()
wg.Wait()
fmt.Println("first post id is", firstPostID)
fmt.Println("second post id is", secondPostID)
fmt.Println("second post title is", secondPostName)
}
There are three goroutines, so I have 3 concurrent requests, I sync everything using sync.Workgroup
. The following code is implementation of the requests:
func makeRequest(url string) Post {
resp, err := http.Get(url)
if err != nil {
// handle error
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
var post Post
json.Unmarshal(body, &post)
return post
}
func makeFirstPostRequest() Post {
return makeRequest("https://jsonplaceholder.typicode.com/todos/1")
}
func makeSecondPostRequest() Post {
return makeRequest("https://jsonplaceholder.typicode.com/todos/2")
}
Here is implementation of functions which pulls needed information from fetched posts:
func getFirstPostID() int {
var result = makeFirstPostRequest()
return result.ID
}
func getSecondPostID() int {
var result = makeSecondPostRequest()
return result.ID
}
func getSecondPostName() string {
var result = makeSecondPostRequest()
return result.Title
}
So, at the moment I have 3 concurrent requests, this works perfectly. The problem is I don't want 2 absolutely same separate HTTP requests to fetch the second post. One would be enough. So, what I want to achieve is 2 concurrent requests for post 1 and post 2. I want second call to makeSecondPostRequest
not to create new HTTP request, but share the existing one (which was sent by the first call).
How I can achieve this?
Note: the following code is how this can be done using JavaScript, for example.
let promise = null;
function makeRequest() {
if (promise) {
return promise;
}
return promise = fetch('https://jsonplaceholder.typicode.com/todos/1')
.then(result => result.json())
// clean up cache variable, so any next request in the future will be performed again
.finally(() => (promise = null))
}
function main() {
makeRequest().then((post) => {
console.log(post.id);
});
makeRequest().then((post) => {
console.log(post.title);
});
}
main();
See Question&Answers more detail:
os