News for hackers. Stuff that matters.
Re:Go kit: Go in the modern enterprise by Zikes on Wednesday February 11, 2015 @11:10PM (#9037327)
They 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.

Re:Go kit: Go in the modern enterprise by codygman on Wednesday February 11, 2015 @11:53PM (#9037452)
How 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?

Re:Go kit: Go in the modern enterprise by Zikes on Thursday February 12, 2015 @12:09AM (#9037497)
How 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-idiom...
Re:Go kit: Go in the modern enterprise by sagichmal on Thursday February 12, 2015 @03:32AM (#9037979)
PurchaseType doesn't need to be stringly typed. See 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
Re:Go kit: Go in the modern enterprise by codygman on Thursday February 12, 2015 @12:16AM (#9037514)
Check 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.

Re:Go kit: Go in the modern enterprise by 4ydx on Thursday February 12, 2015 @12:27AM (#9037557)
There is no exhaustive pattern matching in golang. And you would have to define your own unmarshall function that translates "Rent" into, perhaps, a const. So, yes, type safety in golang is not as powerful as it is in Haskell. I think we already knew that though didn't we :)
Re:Go kit: Go in the modern enterprise by codygman on Thursday February 12, 2015 @12:57AM (#9037627)
> So, yes, type safety in golang is not as powerful as it is in Haskell. I think we already knew that though didn't we :)

That is just a really big one for me I wanted to share and get others opinion on. I guess I just feel like a lot of people don't realize how much having that stringly typed hole means. Perhaps others just disagree.

I would love to hear a counter argument for why others don't think this matters.

Re:Go kit: Go in the modern enterprise by NateDad on Thursday February 12, 2015 @09:55AM (#9038981)
I've been coding professionally for 16 years. I've written a lot of this kind of code:

    switch (someEnum) {
      case foo:
        <something>
      case bar:
        <something>
      default:
        throw DeveloperScrewedUpException("Unknown enum val: " + someEnum)
    }
...You know how often I've seen those exceptions? Never. Not once. I'm not saying it can't happen, and I'm not saying that I wouldn't want a compiler error to tell me I missed a value... but I am saying that it just doesn't actually happen all that often in my experience, especially with decent tests. And yes, I've worked on systems for many years where they've evolved and things have changed significantly, so it's not just that I've only worked on brand new projects.