4 ms·
If I recall correctly those libraries aren't type safe and composable, but perhaps I'm remembering wrong.
by codygman 12y ago
If I recall correctly those libraries aren't type safe and composable, but perhaps I'm remembering wrong.
- elithrar 12y ago> If I recall correctly those libraries aren't type safe and composable You may be confusing interfaces (which enforce type compatibility) and the empty interface{}, which is effectively a dynamic type in the Go world.
- Zikes 12y agoThey are type safe, except for the unsafe package but it's hard not to know what you're getting into with that one. One of the best examples of composability is the Reader and Writer interface. They're designed to operate on slices of bytes, so a package intended to read from a Reader can read from files, stdin, networks, sockets, and a myriad other systems with absolutely no changes to the package's code or its implementation.
- codygman 12y agoHow would you do decode this json in a type safe way using Go? {"purchaseType": "Rent","price": 0.99,"title": "inception"} Here is an implementation in Haskell: {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE OverloadedStrings #-} import Data.Aeson import GHC.Generics import qualified Data.ByteString.Lazy as BL data PurchaseType = Free | Rent | Buy | Subscriber deriving (Show, Generic) instance FromJSON PurchaseType instance ToJSON PurchaseType data Media = Media { title :: String, price :: Float, purchaseType :: PurchaseType} deriving (Show, Generic) instance FromJSON Media instance ToJSON Media jsonData = "{\"title\": \"inception\", \"price\": 0.99, \"purchaseType\": \"Rent\"}" main = print $ (decode jsonData :: Maybe Media) -- running main gets: -- λ> main -- Just (Media {title = "inception", price = 0.99, purchaseType = Rent}) EDIT: Spec Change, boss wants an order confirmation message! orderConfirmationMessage (Media mediaTitle _ Rent) = putStrLn ("Thanks for renting " ++ mediaTitle) Then we recompile and... what's this? Main.hs:19:1-100: Warning: … Pattern match(es) are non-exhaustive In an equation for ‘orderConfirmationMessage’: Patterns not matched: Media _ _ Free Media _ _ Buy Media _ _ Subscriber Good thing GHC had told us Free/Buy/Subscriber's needed messages instead of our boss! In fact, had I been using -Wall this would be a compile time error. Getting to the point, my real questions are: 1. What is Go's way of ensuring your function handles cases like this, or is there an idiomatic way of avoiding it? 2. How do you discern between MovieType's without resorting to just using Strings and compromising type safety?
- Zikes 12y agoHow about an array of Media? package main import ( "encoding/json" "fmt" ) type Media struct { Title string Price float64 PurchaseType string } func main() { jsonData := []byte(` [ {"purchaseType":"Rent","price":0.99,"title":"Inception"}, {"purchaseType":"Free","price":0.00,"title":"Johnny Mnemonic"}, {"purchaseType":"Buy","price":17.99,"title":"John Wick"} ] `) var media []Media err := json.Unmarshal(jsonData, &media) if err != nil { fmt.Println("error: ", err) } fmt.Printf("%+v\n", media) } Output: $ go run main.go [{Title:Inception Price:0.99 PurchaseType:Rent} {Title:Johnny Mnemonic Price:0 PurchaseType:Free} {Title:John Wick Price:17.99 PurchaseType:Buy}] Edit: Regarding the MediaType: http://stackoverflow.com/questions/14426366/what-is-an-idiomatic-way-of-representing-enums-in-golang http://stackoverflow.com/questions/14426366/what-is-an-idiom...
- codygman 12y agoCheck out my update if you haven't seen it already. tl;dr The problem for me personally is when you start making functions based on the type of media and sacrifice type safety if MediaType is a string.
- sagichmal 12y agoPurchaseType doesn't need to be stringly typed. See https://talks.golang.org/2015/json.slide#1 https://talks.golang.org/2015/json.slide#1. type PurchaseType byte const ( Free PurchaseType = iota Rent Buy ) func (t *PurchaseType) UnmarshalJSON(data []byte) error { var s string if err := json.Unmarshal(data, &s); err != nil { return fmt.Errorf("purchase type should be a string, got %s", data) } have, ok := map[string]PurchaseType{"Free": Free, "Rent": Rent, "Buy": Buy}[s] if !ok { return fmt.Errorf("invalid purchase type %q", s) } *t = have return nil } That's enough to give this output: [{Inception 0.99 Rent} {Johnny Mnemonic 0 Free} {John Wick 17.99 Buy}] http://play.golang.org/p/dyNVlgmFtu http://play.golang.org/p/dyNVlgmFtu
- 12y ago