Like, I get that the extra type-pointer for a declared struct of float64+bool isn't that big of a deal, I do wish we could express tuple types naturally. What you suggest is probably the closest we get for now. For `if v, ok := value.(bool); ok && v`, the value is tuly 0. For `if v, ok := value.(bool); ok && !v`, the value is truly nil. For `if v, ok := value.(float64); ok`, the value can be known to be properly and truly the value, even if `0.0`. This would extend to any other type I can think of, excepting, naturally, bools.
Meanwhile, did you see the half-serious sigma-type proposal? I'm pretty sure that would effectively resolve this question, as little hope as I have for it to be accepted. On Wednesday, April 6, 2022 at 4:01:32 AM UTC-5 Brian Candler wrote: > I agree, and there's a clear benefit that it's harder to dereference a nil > interface than a nil pointer, when that interface has no methods. The > problem is that statically it doesn't tell you anything about the possible > contained type. > > In comparison, a pointer tells you exactly the type contained, but it must > be exactly one type, and there's always a risk of accidentally deferencing > a nil pointer. > > If one day, generics type-constraint interfaces could be used as regular > interface types, that would be powerful: you could have a variable of type > "interface { float64 | Status }" and know for sure that the value *must* be > either nil, float64 or Status. Furthermore, you wouldn't be able to use the > contained value without an explicit type assertion. > > On Wednesday, 6 April 2022 at 01:10:23 UTC+1 sam.a....@gmail.com wrote: > >> I get what you're saying, and for what it's worth, you're absolutely >> correct. Something like above is a set of tradeoffs, and I guess all I can >> assert is that it works for me. I do think it's a good design, given Go's >> lack of a None<T> type to enforce well-defined behavior on a nil pointer >> dereference, but it's an example of a well-designed API from the days >> before generics, which safely respects nil/null values in the appropriate >> context. >> >> For most of my use of the model, the types offered by the pgtype pacakge >> are A. total overkill, and B. just an intermediate type to hold a value >> between two boundaries that do understand null values, such as bridging an >> RPC frontend and a SQL backend. >> >> If anything, it proves that Generics do simplify codebases, and that >> well-defined, graceful null/nil handling is worth the effort. >> On Tuesday, April 5, 2022 at 5:13:04 AM UTC-5 Brian Candler wrote: >> >>> I did look at the code briefly. The main thing I noticed was that the >>> return type of float8.Get() was an interface{} - so it's up to the caller >>> to check at runtime whether the value is nil, a float64, or a Status. >>> >>> So you're right, it's not that they are compile-time unsafe, but rather >>> that you have to write type matching code at each use site. Within a given >>> switch branch, it's safe. >>> >>> On Tuesday, 5 April 2022 at 07:29:09 UTC+1 sam.a....@gmail.com wrote: >>> >>>> Uh, you should check the code: >>>> github.com/jackc/pgtype/blob/master/float8.go If you know what you >>>> have and what you're dealing with, and if you actually check the error >>>> result, you do get safety. If you don't know what you've got, or if you're >>>> iterating through the values, then you end up hitting the sad, sad, >>>> reflective path...for now. >>>> On Saturday, April 2, 2022 at 4:37:36 AM UTC-5 Brian Candler wrote: >>>> >>>>> Correct repository path is: https://github.com/jackc/pgtype >>>>> >>>>> Interesting. These structs generally contain a Status value as well: >>>>> >>>>> type Int8 struct { >>>>> Int int64 >>>>> Status Status >>>>> } >>>>> >>>>> where pgtype.go has: >>>>> >>>>> type Status byte >>>>> >>>>> const ( >>>>> Undefined Status = iota >>>>> Null >>>>> Present >>>>> ) >>>>> >>>>> They also have Set() and Get() methods, although these are not >>>>> compiled-time type safe as they accept and return interface{} >>>>> >>>>> On Friday, 1 April 2022 at 17:40:42 UTC+1 sam.a....@gmail.com wrote: >>>>> >>>>>> >>>>>> Thanks for clarifying that, @Brian. Yeah. It took a bit to warm up to >>>>>> that approach, but the github.com/jackc/pgtypes convinced me that >>>>>> the results were worth it. The benefits: A, package interpretation >>>>>> methods >>>>>> with a piece of data, B, lazily valuate data when needed, and C, gain >>>>>> introspective capability specific to the type and not using reflect >>>>>> On Friday, April 1, 2022 at 4:47:32 AM UTC-5 Brian Candler wrote: >>>>>> >>>>>>> That wasn't literal code with anglebrackets - you're supposed to >>>>>>> fill that in yourself. I think he meant something like: >>>>>>> >>>>>>> type fooString struct{ string } >>>>>>> >>>>>>> https://go.dev/play/p/4Q94xMZDciV >>>>>>> >>>>>>> What this is doing is *embedding* a string value into a struct; if >>>>>>> you have not come across type embedding before then Google for the >>>>>>> details. >>>>>>> >>>>>>> You still cannot use one of these types transparently as a string, >>>>>>> but you can use >>>>>>> x.string >>>>>>> instead of >>>>>>> string(x) >>>>>>> to extract the value. >>>>>>> >>>>>>> On Friday, 1 April 2022 at 06:48:04 UTC+1 yan.z...@gmail.com wrote: >>>>>>> >>>>>>>> Hi Sam! Your solution does not seem to work: >>>>>>>> >>>>>>>> package main >>>>>>>> >>>>>>>> import( >>>>>>>> "fmt" >>>>>>>> "strconv" >>>>>>>> ) >>>>>>>> >>>>>>>> type <Purpose> String struct{string} >>>>>>>> >>>>>>>> func (s String) print(){ >>>>>>>> fmt.Println(s) >>>>>>>> } >>>>>>>> >>>>>>>> func main() { >>>>>>>> var a String ="hello, world\n" >>>>>>>> >>>>>>>> a.print() >>>>>>>> >>>>>>>> fmt.Println(strconv.ParseInt("78",10, 64)) >>>>>>>> >>>>>>>> var x String ="452" >>>>>>>> >>>>>>>> n, _ := strconv.ParseInt(x, 10, 64) >>>>>>>> } >>>>>>>> >>>>>>>> 在2022年3月26日星期六 UTC+8 06:41:15<sam.a....@gmail.com> 写道: >>>>>>>> >>>>>>>>> >>>>>>>>> My workaround like is something like `type <Purpose>String >>>>>>>>> struct{string}. It can be reasonably treated as a string for most >>>>>>>>> cases in >>>>>>>>> which as string is needed, and it lets you convert back conveniently >>>>>>>>> from >>>>>>>>> any scope in which it's reasonable for your program to know the >>>>>>>>> difference. >>>>>>>>> On Friday, March 18, 2022 at 12:46:34 AM UTC-5 Henry wrote: >>>>>>>>> >>>>>>>>>> My own preference is to have a small number of methods and put >>>>>>>>>> the general functionalities into functions. By putting the general >>>>>>>>>> functionalities into functions, you allow code reuse. In >>>>>>>>>> object-oriented >>>>>>>>>> programming, you normally attach as many functionalities as possible >>>>>>>>>> to >>>>>>>>>> their corresponding types and achieve code reuse via inheritance. >>>>>>>>>> Since Go >>>>>>>>>> does not have inheritance, you can achieve a similar effect with >>>>>>>>>> standalone >>>>>>>>>> functions. >>>>>>>>>> >>>>>>>>>> On Friday, March 18, 2022 at 11:26:51 AM UTC+7 Ian Lance Taylor >>>>>>>>>> wrote: >>>>>>>>>> >>>>>>>>>>> On Thu, Mar 17, 2022 at 7:17 PM Zhaoxun Yan <yan.z...@gmail.com> >>>>>>>>>>> wrote: >>>>>>>>>>> > >>>>>>>>>>> > I just came across this taboo in golang - new methods cannot >>>>>>>>>>> be added to an existing type: >>>>>>>>>>> >>>>>>>>>>> Yes. If we didn't have this prohibition, then the set of >>>>>>>>>>> interfaces >>>>>>>>>>> satisfied by a type would depend on which package was using the >>>>>>>>>>> type. >>>>>>>>>>> >>>>>>>>>>> See the discussion at https://go.dev/issue/21401. >>>>>>>>>>> >>>>>>>>>>> Ian >>>>>>>>>>> >>>>>>>>>> -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/3868fa3a-3a94-43b4-888c-d3f2f27b58ean%40googlegroups.com.