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.

Reply via email to