11,232 karma · joined August 9, 2010
let s = “asd”;
println!(“{}”, s[0]);
You will get a compiler error telling you that you cannot index into &str.https://github.com/golang/go/issues/32334
oops, looks like some files are just inaccessible to you, and you cannot copy them.
Fortunately, when you try to delete the source directory, Go's standard library enters infinite loop, which saves your data.
Yes, and that's a good thing. It allows every code that gets &str/String to assume that the input is valid UTF-8. The alternative would be that every single time you write a function that takes a string as an argument, you have to analyze your code, consider what would happen if the argument was not valid UTF-8, and handle that appropriately. You'd also have to redo the whole analysis every time you modify the function. That's a horrible waste of time: it's much better to:
1) Convert things to String early, and assume validity later, and
2) Make functions that explicitly don't care about validity take &[u8] instead.
This is, of course, exactly what Rust does: I am not aware of a single thing that &str allows you to do that you cannot do with &[u8], except things that do require you to assume it's valid UTF-8.
If your API takes &str, and tries to do byte-based indexing, it should almost certainly be taking &[u8] instead.
Every single thing you listed here is supported by &[u8] type. That's the point: if you want to operate on data without assuming it's valid UTF-8, you just use &[u8] (or allocating Vec<u8>), and the standard library offers what you'd typically want, except of the functions that assume that the string is valid UTF-8 (like e.g. iterating over code points). If you want that, you need to convert your &[u8] to &str, and the process of conversion forces you to check for conversion errors.
I'd say that it's entirely the other way around: they stuck to the practical convenience of solving the problem that they had in front of them, quickly, instead of analyzing the problem from the first principles, and solving the problem correctly (or using a solution that was Not Invented Here).
Go's filesystem API is the perfect example. You need to open files? Great, we'll create
func Open(name string) (*File, error)
function, you can open files now, done. What if the file name is not valid UTF-8, though? Who cares, hasn't happen to me in the first 5 years I used Go.To be specific: let's say that you own $1.1B worth of stock, $1B of which is unrealized long term capital gains. If you sold it all today, you'd owe $200M. Let's say that you're 40, you spend $5M a year, and you die at 80. So, you need $200M to finance your lifestyle, and then the remainder is a part of your estate. If you just sold $240M today, you'd pay $40M in tax, and had $200M after tax cash in your checking account to spend over the next 40 years. If you instead borrow $5M a year against your stock at very attractive terms like interest rate of 5%, and no payments until your death, you'll owe $200M on interest over these 40 years. Just paying the tax would have saved you $160M! It's even worse if you get more realistic terms, because 5% rate on a personal loan is too good to be true, and you'll need to borrow even more to make the regular payments.
What about the remainder of your estate? Depending on whether you just sell as you go, or borrow to finance your spending, your estate is left with something between $500M and $800M. Guess what, now they owe estate tax, which is 40% of this sum (minus $30M exemption). Oops!
You can avoid the estate tax, though, but the kicker is that all of the ways of doing that do not allow you to step up the basis upon death: they just allow you to avoid the gift tax, but they do little to escape the capital gains income tax. No free lunch here either.
How does that work? I thought that this vulnerability was independent of the curve that is used. Ed25519 has a bunch of other nice properties related to resistance to programming errors, but I never heard of this one.