{"action":"created","issue":{"url":"https://api.github.com/repos/golang/go/issues/19814","repository_url":"https://api.github.com/repos/golang/go","labels_url":"https://api.github.com/repos/golang/go/issues/19814/labels{/name}","comments_url":"https://api.github.com/repos/golang/go/issues/19814/comments","events_url":"https://api.github.com/repos/golang/go/issues/19814/events","html_url":"https://github.com/golang/go/issues/19814","id":218638547,"number":19814,"title":"proposal: spec: add typed enum support","user":{"login":"derekperkins","id":3588778,"avatar_url":"https://avatars0.githubusercontent.com/u/3588778?v=4","gravatar_id":"","url":"https://api.github.com/users/derekperkins","html_url":"https://github.com/derekperkins","followers_url":"https://api.github.com/users/derekperkins/followers","following_url":"https://api.github.com/users/derekperkins/following{/other_user}","gists_url":"https://api.github.com/users/derekperkins/gists{/gist_id}","starred_url":"https://api.github.com/users/derekperkins/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/derekperkins/subscriptions","organizations_url":"https://api.github.com/users/derekperkins/orgs","repos_url":"https://api.github.com/users/derekperkins/repos","events_url":"https://api.github.com/users/derekperkins/events{/privacy}","received_events_url":"https://api.github.com/users/derekperkins/received_events","type":"User","site_admin":false},"labels":[{"id":150880249,"url":"https://api.github.com/repos/golang/go/labels/Go2","name":"Go2","color":"ffaaaa","default":false},{"id":150880200,"url":"https://api.github.com/repos/golang/go/labels/LanguageChange","name":"LanguageChange","color":"ffaaaa","default":false},{"id":373402289,"url":"https://api.github.com/repos/golang/go/labels/NeedsInvestigation","name":"NeedsInvestigation","color":"ededed","default":false},{"id":236419512,"url":"https://api.github.com/repos/golang/go/labels/Proposal","name":"Proposal","color":"ededed","default":false}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":{"url":"https://api.github.com/repos/golang/go/milestones/30","html_url":"https://github.com/golang/go/milestone/30","labels_url":"https://api.github.com/repos/golang/go/milestones/30/labels","id":1373555,"number":30,"title":"Proposal","description":"Proposals that are pending (not yet accepted/rejected).\r\n","creator":{"login":"rsc","id":104030,"avatar_url":"https://avatars1.githubusercontent.com/u/104030?v=4","gravatar_id":"","url":"https://api.github.com/users/rsc","html_url":"https://github.com/rsc","followers_url":"https://api.github.com/users/rsc/followers","following_url":"https://api.github.com/users/rsc/following{/other_user}","gists_url":"https://api.github.com/users/rsc/gists{/gist_id}","starred_url":"https://api.github.com/users/rsc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rsc/subscriptions","organizations_url":"https://api.github.com/users/rsc/orgs","repos_url":"https://api.github.com/users/rsc/repos","events_url":"https://api.github.com/users/rsc/events{/privacy}","received_events_url":"https://api.github.com/users/rsc/received_events","type":"User","site_admin":false},"open_issues":185,"closed_issues":497,"state":"open","created_at":"2015-10-24T01:40:49Z","updated_at":"2018-05-14T21:19:53Z","due_on":null,"closed_at":null},"comments":138,"created_at":"2017-03-31T23:07:08Z","updated_at":"2018-05-15T01:01:59Z","closed_at":null,"author_association":"NONE","body":"I'd like to propose that enum be added to Go as a special kind of `type`. The examples below are borrowed from the protobuf example.\r\n\r\n### Enums in Go today\r\n```\r\ntype SearchRequest int\r\nvar (\r\n\tSearchRequestUNIVERSAL SearchRequest = 0 // UNIVERSAL\r\n\tSearchRequestWEB       SearchRequest = 1 // WEB\r\n\tSearchRequestIMAGES    SearchRequest = 2 // IMAGES\r\n\tSearchRequestLOCAL     SearchRequest = 3 // LOCAL\r\n\tSearchRequestNEWS      SearchRequest = 4 // NEWS\r\n\tSearchRequestPRODUCTS  SearchRequest = 5 // PRODUCTS\r\n\tSearchRequestVIDEO     SearchRequest = 6 // VIDEO\r\n)\r\n\r\ntype SearchRequest string\r\nvar (\r\n\tSearchRequestUNIVERSAL SearchRequest = \"UNIVERSAL\"\r\n\tSearchRequestWEB       SearchRequest = \"WEB\"\r\n\tSearchRequestIMAGES    SearchRequest = \"IMAGES\"\r\n\tSearchRequestLOCAL     SearchRequest = \"LOCAL\"\r\n\tSearchRequestNEWS      SearchRequest = \"NEWS\"\r\n\tSearchRequestPRODUCTS  SearchRequest = \"PRODUCTS\"\r\n\tSearchRequestVIDEO     SearchRequest = \"VIDEO\"\r\n)\r\n\r\n// IsValid has to be called everywhere input happens, or you risk bad data - no guarantees\r\nfunc (sr SearchRequest) IsValid() bool {\r\n\tswitch sr {\r\n\t\tcase SearchRequestUNIVERSAL, SearchRequestWEB...:\r\n\t\t\treturn true\r\n\t}\r\n\treturn false\r\n}\r\n```\r\n\r\n### How it might look with language support\r\n```\r\nenum SearchRequest int {\r\n    0 // UNIVERSAL\r\n    1 // WEB\r\n    2 // IMAGES\r\n    3 // LOCAL\r\n    4 // NEWS\r\n    5 // PRODUCTS\r\n    6 // VIDEO\r\n}\r\n\r\nenum SearchRequest string {\r\n    \"UNIVERSAL\"\r\n    \"WEB\"\r\n    \"IMAGES\"\r\n    \"LOCAL\"\r\n    \"NEWS\"\r\n    \"PRODUCTS\"\r\n    \"VIDEO\"\r\n}\r\n```\r\n\r\nThe pattern is common enough that I think it warrants special casing, and I believe that it makes code more readable. At the implementation layer, I would imagine that the majority of cases can be checked at compile time, some of which already happen today, while others are near impossible or require significant tradeoffs.\r\n - **Safety for exported types**: nothing prevents someone from doing `SearchRequest(99)` or `SearchRequest(\"MOBILEAPP\")`. Current workarounds include making an unexported type with options, but that often makes the resulting code harder to use / document.\r\n - **Runtime safety**: Just like protobuf is going to check for validity while unmarshaling, this provides language wide validation, anytime that an enum is instantiated.\r\n - **Tooling / Documentation**: many packages today put valid options into field comments, but not everyone does it and there is no guarantee that the comments aren't outdated.\r\n\r\n### Things to Consider\r\n - **Nil**: by implementing `enum` on top of the type system, I don't believe this should require special casing.  If someone wants `nil` to be valid, then the enum should be defined as a pointer.\r\n - **Default value / runtime assignments**: This is one of the tougher decisions to make. What if the Go default value isn't defined as a valid enum? Static analysis can mitigate some of this at compile time, but there would need to be a way to handle outside input.\r\n\r\nI don't have any strong opinions on the syntax. I do believe this could be done well and would make a positive impact on the ecosystem."},"comment":{"url":"https://api.github.com/repos/golang/go/issues/comments/389009228","html_url":"https://github.com/golang/go/issues/19814#issuecomment-389009228","issue_url":"https://api.github.com/repos/golang/go/issues/19814","id":389009228,"user":{"login":"jimmyfrasche","id":375553,"avatar_url":"https://avatars1.githubusercontent.com/u/375553?v=4","gravatar_id":"","url":"https://api.github.com/users/jimmyfrasche","html_url":"https://github.com/jimmyfrasche","followers_url":"https://api.github.com/users/jimmyfrasche/followers","following_url":"https://api.github.com/users/jimmyfrasche/following{/other_user}","gists_url":"https://api.github.com/users/jimmyfrasche/gists{/gist_id}","starred_url":"https://api.github.com/users/jimmyfrasche/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jimmyfrasche/subscriptions","organizations_url":"https://api.github.com/users/jimmyfrasche/orgs","repos_url":"https://api.github.com/users/jimmyfrasche/repos","events_url":"https://api.github.com/users/jimmyfrasche/events{/privacy}","received_events_url":"https://api.github.com/users/jimmyfrasche/received_events","type":"User","site_admin":false},"created_at":"2018-05-15T01:01:59Z","updated_at":"2018-05-15T01:01:59Z","author_association":"CONTRIBUTOR","body":"@ianlancetaylor that's a very C version of enums you're talking about. I'm sure a lot of people but would like that but, imo:\r\n\r\nEnum values should not have any numeric properties. The values of each enum type should be their own finite universe of discrete labels, enforced at compile time, unrelated to any numbers or other enum types. The only thing you can do with a pair of such values is `==` or `!=`. Other operations can be defined as methods or with functions.\r\n\r\nThe implementation is going to compile those values down to integers but that's not a fundamental thing with any legitimate reason to be exposed directly to the programmer, except by unsafe or reflection. For the same reason that you can't do `bool(0)` to get `false`.\r\n\r\nIf you want to convert an enum to or from a number or any other type, you write out all the cases and include error handling appropriate to the situation. If that's tedious, you use a code generator like stringer or at least something to fill out the cases in the switch statement.\r\n\r\nIf you're sending the value out of process, an int is good if you're following a well-defined standard or you know you're talking to another instance of your program that was compiled from the source or you need to make things fit in the smallest space possible even if that might cause problems, but generally none of these hold and it's better to use a string representation so the value is unaffected by the source order of the type definition. You don't want process A's Green to become process B's Blue because someone else decided Blue should be added before Green to keep things alphabetical in the definition: you want `unrecognized color \"Blue\"`.\r\n\r\nIt's a good, safe way to represent a number of states abstractly. It leaves the program to define what those states mean.\r\n\r\n(Of course, often you want to associate data with those states and the type of that data varies from state to state  . . .)"}}
{"actor":{"display_login":"jimmyfrasche"}}