Skip to content

Instantly share code, notes, and snippets.

@kevinburke
Last active April 3, 2016 22:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save kevinburke/420afcc1cb1116ac1c5a91af900fd702 to your computer and use it in GitHub Desktop.
Save kevinburke/420afcc1cb1116ac1c5a91af900fd702 to your computer and use it in GitHub Desktop.
package main
import (
"encoding/json"
"fmt"
"net"
"net/http"
"sync"
)
type JsonIpResponse struct {
IP net.IP `json:"ip"`
}
type IpInfoResponse struct {
IP net.IP `json:"ip"`
}
func makeJsonipRequest() (JsonIpResponse, error) {
resp, err := http.Get("http://jsonip.com")
if err != nil {
return JsonIpResponse{}, err
}
var jip JsonIpResponse
defer resp.Body.Close()
err = json.NewDecoder(resp.Body).Decode(&jip)
return jip, err
}
func ipInfoRequest() (IpInfoResponse, error) {
req, err := http.NewRequest("GET", "http://ipinfo.io", nil)
if err != nil {
return IpInfoResponse{}, err
}
req.Header.Add("Accept", "application/json")
req.Header.Add("User-Agent", "HTTPie/1.0.0-dev")
//b, _ := httputil.DumpRequestOut(req, true)
//os.Stderr.Write(b)
resp, err := http.DefaultClient.Do(req)
//r := io.TeeReader(resp.Body, os.Stdout)
if err != nil {
return IpInfoResponse{}, err
}
var jip IpInfoResponse
defer resp.Body.Close()
err = json.NewDecoder(resp.Body).Decode(&jip)
return jip, err
}
func main() {
var jipr JsonIpResponse
var jerr error
var ipr IpInfoResponse
var ierr error
// These two functions can be anything you want to do in parallel;
// - make internal HTTP requests for billing info, account info, and fraud scores
// - read records from different database tables
//
// This was the simplest example I could demonstrate, that would run.
var wg sync.WaitGroup
go func() {
ipr, ierr = ipInfoRequest()
wg.Done()
}()
wg.Add(1)
go func() {
jipr, jerr = makeJsonipRequest()
wg.Done()
}()
wg.Add(1)
wg.Wait()
fmt.Println("jsonip.com ip result:", jipr)
fmt.Println("ipinfo.io ip result:", ipr)
}
var compareIps = function(userId, pickupId) {
return Promise.join(
getJsonIp(),
getIpInfoIp()
).spread(function(ipinfoIp, jsonIp) {
console.log(ipinfoIp);
console.log(jsonIp);
}).catch(function(err){
console.error(err);
process.exit(1);
})
}
@kevinburke
Copy link
Author

Here's a slightly more cleaned up example. You wouldn't be able to reuse the same channel if you were fetching values of different types, but it's a little cleaner. https://gist.github.com/nilium/2ce96b86aba257d52a84376fb3b314e8

@shazow
Copy link

shazow commented Apr 3, 2016

What's the implementation of getJsonIp and getIpInfoIp? I presume they return Promise objects? So an equivalent would be async Go funcs that return channels? If we're contriving it like that, then the code becomes a lot more similar:

ch1 := getJsonIp()
ch2 := getIpInfoIp()

ip1 := <-ch1
if ip1.err != nil { ... }
ip2 := <-ch2
if ip2.err != nil { ... }

fmt.Println(ip1, ip2)

Or could have somekind of container struct that knows about both fetching types and use a scanner pattern to check for errors.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment