WEBVTT 0 00:00.520 --> 00:01.570 Welcome back. 1 00:01.570 --> 00:07.960 In this lecture, you will learn how to extract the dynamic value inside an interface value. 2 00:07.960 --> 00:10.510 Let's take a look at an example. 3 00:10.630 --> 00:16.690 First, I'm going to comment out store.print() to keep the output clear. 4 00:16.690 --> 00:18.820 I'm going to declare a printer. 5 00:19.030 --> 00:22.980 This variable stores a printer interface value. 6 00:23.080 --> 00:29.380 Let me print it. As you can see, the zero value of an interface value is nil. 7 00:29.380 --> 00:31.070 Let me print it. As you can see, the zero value of an interface value is nil. 8 00:31.120 --> 00:35.740 It doesn't store any value yet. As an example, 9 00:35.740 --> 00:41.230 let's assign it a game value and print it. 10 00:41.450 --> 00:44.030 It works. As you can see, 11 00:44.120 --> 00:52.580 you can assign it any value of a type as long as the type has a print method. A game type has a lot of 12 00:52.580 --> 00:54.990 fields and methods. 13 00:55.040 --> 01:00.460 For example I can call the discount method like this. 14 01:00.600 --> 01:01.870 It works. 15 01:01.890 --> 01:06.720 Now I'm going to call the discount method on the P variable. 16 01:06.720 --> 01:11.250 After all the interface variable p stores a game value. 17 01:11.760 --> 01:17.640 However I cannot call the discount method on the interface variable ("p"). 18 01:17.640 --> 01:22.140 It's because the interface variable ("p") is another game value. 19 01:22.320 --> 01:30.390 It's a printer interface variable so it doesn't let us access the discount method. 20 01:30.390 --> 01:37.050 Let's talk about this a little bit more let's create a game variable. 21 01:37.050 --> 01:39.770 This is what the Tetris variable looks like. 22 01:39.780 --> 01:44.530 It is a pointer to a game value and it has two methods on it. 23 01:44.550 --> 01:50.380 Print and discount you can call the print method it works. 24 01:50.520 --> 01:53.580 You can call the discount method as well. 25 01:53.580 --> 01:56.670 It also works so far so good. 26 01:56.670 --> 02:02.280 Now let's see what happens when you put it into a printer interface value. 27 02:02.280 --> 02:06.740 When I do so the interface value wraps the game value. 28 02:06.900 --> 02:12.810 Remember from the previous coding example that the variable p stores the interface value. 29 02:13.050 --> 02:15.360 I can call the print method on it. 30 02:15.360 --> 02:19.620 It's because there is a print method on the printer interface. 31 02:19.680 --> 02:26.850 However I can no longer call the discount method it's because there is no discount method on the printer 32 02:26.880 --> 02:34.780 interface as you can see an interface value wraps and hides the wrapped value. 33 02:35.120 --> 02:39.830 So you can only use the methods provided by the interface. 34 02:39.980 --> 02:48.500 Actually this is one of the reasons for using an interface it isolates and decouples one part of the 35 02:48.500 --> 02:50.420 code from another. 36 02:50.420 --> 02:57.400 If you could access the other methods there wouldn't be any need for using an interface. 37 02:57.620 --> 03:05.150 By the way the wrapped value inside that interface value is also called a dynamic value. 38 03:05.150 --> 03:11.840 It's a dynamic value because the value in an interface value can change in the runtime. 39 03:11.840 --> 03:21.420 You can assign a different value as long as it satisfies the interface so an interface value has two 40 03:21.420 --> 03:22.230 parts. 41 03:22.380 --> 03:24.910 The first part is the dynamic value. 42 03:25.020 --> 03:29.530 It is the value that is wrapped in an interface value. 43 03:29.580 --> 03:32.640 The second part is the dynamic type. 44 03:32.640 --> 03:37.690 It is the type of value that you are storing in an interface value. 45 03:37.740 --> 03:41.570 It is dynamic so you can change it in runtime here. 46 03:41.610 --> 03:49.230 The type of this interface value is a printer so you can assign it any type that satisfies the printer 47 03:49.320 --> 03:51.270 interface. 48 03:51.350 --> 03:57.100 So how can you extract the dynamic value from an interface value to do that. 49 03:57.140 --> 03:59.420 You need to use a type assertion. 50 03:59.420 --> 04:08.840 It looks like this when you use it it extracts and returns you the dynamic value the return value is 51 04:08.840 --> 04:17.810 the real game value that you put into the interface value you get what you put. 52 04:17.900 --> 04:23.260 This is the interface value you can extract the dynamic value from it. 53 04:23.300 --> 04:27.680 To do that you need to type the dynamic values type. 54 04:27.680 --> 04:32.600 This type is dynamic type that is stored in the interface value. 55 04:33.320 --> 04:41.530 It's like saying I know there is a game pointer in you give me what you are hiding if it's a book you 56 04:41.530 --> 04:43.440 just need to type book. 57 04:43.630 --> 04:46.920 If it's a puzzle you just need to say puzzle. 58 04:47.050 --> 04:47.920 And so on. 59 04:48.460 --> 04:51.320 Okay let's take a look at an example. 60 04:51.880 --> 04:56.530 Let's say I want to discount all the games in my store. 61 04:56.530 --> 05:00.760 So I'm going to call the discount method like this. 62 05:00.850 --> 05:03.880 However it doesn't exist yet. 63 05:03.880 --> 05:12.970 So let's create a discount method on the list like so. It takes a discount ratio just like the discount 64 05:12.970 --> 05:22.270 method in the game type inside I'm going to loop and I'm going to say it.discount(ratio). 65 05:22.270 --> 05:26.920 However this will make a discount for every item on the list. 66 05:27.010 --> 05:30.280 But I want to make a discount only to the games. 67 05:30.310 --> 05:33.730 Besides that this code doesn't work. 68 05:33.730 --> 05:35.050 But why? 69 05:35.050 --> 05:39.860 Remember every item on the list is a printer value. 70 05:40.030 --> 05:44.080 But the printer interface doesn't have a discount method. 71 05:44.080 --> 05:49.890 So let's add a discount method to the printer interface to solve this problem. 72 05:49.900 --> 05:50.480 Nice. 73 05:50.560 --> 05:52.980 Doing so solves the problem. 74 05:53.110 --> 05:57.320 However now there is another problem in the main function. 75 05:57.400 --> 06:01.730 Now only the game type satisfies the printer interface. 76 06:01.780 --> 06:05.890 It's because the other types don't have a discount method. 77 06:05.950 --> 06:09.070 So let's get back to the list here. 78 06:09.070 --> 06:11.130 I didn't solve the problem. 79 06:11.140 --> 06:13.810 Instead I created another problem. 80 06:13.870 --> 06:20.140 If there is a lot of types that depend on an interface you cannot easily change the interface. 81 06:20.140 --> 06:22.420 So what should I do? 82 06:22.420 --> 06:27.450 First of all let's remove the discount method from the interface. 83 06:27.490 --> 06:30.150 Now I am back to where I started. 84 06:30.160 --> 06:33.310 I know that only the game type has a discount method. 85 06:34.030 --> 06:40.310 So I'm going to extract the game type using a type assertion. 86 06:40.390 --> 06:45.140 Look I've got a game value and it has a discount method on it. 87 06:45.280 --> 06:51.160 Let's call it these will only discount the game prices. 88 06:51.210 --> 06:54.350 Let's try it. Oops! 89 06:54.370 --> 06:58.080 My program has crashed I'm so unhappy now. 90 06:58.180 --> 06:58.930 What should I do? 91 06:59.440 --> 07:02.320 Let's read the error message first. 92 07:02.350 --> 07:06.430 It says that the printer is a book not a game. 93 07:06.430 --> 07:08.200 What does that mean? 94 07:08.200 --> 07:15.820 Well if you think about it a little bit more you can see that there are many types on the list the game 95 07:15.820 --> 07:18.050 type is only one of them. 96 07:18.280 --> 07:23.910 Here I make a discount to every item not only to games. 97 07:23.920 --> 07:25.560 So what should I do now? 98 07:26.200 --> 07:30.730 How can I check whether the next item is a game or not? 99 07:31.090 --> 07:34.630 This is where the type checking comes into the scene. 100 07:34.630 --> 07:39.340 I can check whether the asserted value is a game or not. 101 07:39.340 --> 07:45.970 To do that I'm going to add a boolean variable here let's print what it does 102 07:50.230 --> 07:58.480 as you can see it only returns true when the next item is a game pointer let's add a condition here 103 07:58.660 --> 08:06.130 like this so that I can apply the discount only to the game values it works. 104 08:06.160 --> 08:12.130 Nice now only the games are discounted. 105 08:12.230 --> 08:13.700 What's next? 106 08:13.700 --> 08:17.530 Let's say I want to make a discount to a new type as well. 107 08:17.990 --> 08:19.890 I'm going to add a toy type. 108 08:20.240 --> 08:26.960 Let's duplicate the game type and I'm going to change the code for the toy type. 109 08:27.370 --> 08:27.910 Okay. 110 08:27.930 --> 08:29.080 Ready. 111 08:29.130 --> 08:31.280 Let's add it to the store. 112 08:31.290 --> 08:38.690 I'm going to create a Yoda toy value and I'm going to add it to the store. 113 08:38.730 --> 08:39.300 Nice. 114 08:39.300 --> 08:40.800 It works. 115 08:40.800 --> 08:42.520 Let's go to the list. 116 08:42.570 --> 08:50.540 I could add another type checking here but it would have complicated the code a lot I will need to use 117 08:50.630 --> 08:54.430 a type assertion whenever I add a new type here. 118 08:55.070 --> 08:58.070 So it's not a very effective way. 119 08:58.070 --> 09:03.650 Instead I'm going to show you something else. Instead of checking for a type, 120 09:03.860 --> 09:05.890 I'm going to check for a behavior. 121 09:05.930 --> 09:13.170 So I'm going to use a type assertion to check whether the next item has a discount method or not. 122 09:13.250 --> 09:19.310 Like this. Remember an interface is just a type. Here, 123 09:19.310 --> 09:24.940 I try to assert whether the next item satisfies this interface. 124 09:25.100 --> 09:30.100 If the next item has a discount method it will satisfy it. 125 09:30.140 --> 09:33.970 So the variable G will have a discount method. 126 09:34.010 --> 09:36.780 That's why I can call it here. 127 09:36.980 --> 09:41.890 By the way here only the types and method names are necessary. 128 09:41.900 --> 09:47.130 So I'm going to remove it let's try it it works. 129 09:47.140 --> 09:48.280 Excellent. 130 09:48.280 --> 09:50.890 We can make this code more readable. 131 09:50.950 --> 09:57.400 To do that I'm going to cut the interface type from here and I'm going to declare it as a discount or 132 09:57.400 --> 09:58.500 interface type. 133 09:58.570 --> 10:00.760 Like so. 134 10:00.890 --> 10:08.030 Lastly I'm going to assert for the discounter type as you can see you don't have to declare an interface 135 10:08.150 --> 10:09.800 at the package level. 136 10:09.800 --> 10:11.080 Let's try it. 137 10:11.180 --> 10:11.720 Cool. 138 10:11.780 --> 10:15.030 It works by using a type assertion. 139 10:15.050 --> 10:21.130 You can also check whether a value provides the method(s) that you want or not. 140 10:21.140 --> 10:28.880 For example here I execute the discount method only if an item value has a discount method. 141 10:28.880 --> 10:34.280 So here the type assertion doesn't extract the dynamic value. 142 10:34.280 --> 10:43.370 Instead it converts the printer interface value to a discounter interface value but only if the value 143 10:43.490 --> 10:45.710 has a discount method. 144 10:45.710 --> 10:49.940 By the way I can also type the assertion more concisely. 145 10:49.940 --> 10:58.520 Remember this is just a short if statement here I declare a new it variable only for the short if 146 10:58.610 --> 11:01.510 statement before the if statement. 147 11:01.600 --> 11:12.680 The it is a printer however the new it here becomes a discounter using the same variable name is just 148 11:12.680 --> 11:14.570 a convention in go. 149 11:14.660 --> 11:22.050 By doing so we also convey the meaning that the it variable is not only a printer, 150 11:22.130 --> 11:25.490 it's also a discounter. 151 11:25.500 --> 11:30.940 In summary there are two use cases for a type assertion. 152 11:30.990 --> 11:37.710 First you can use it to extract the dynamic value from an interface value. 153 11:37.710 --> 11:46.260 Second you can use it to check whether an interface value provides the methods that you want or not. 154 11:46.260 --> 11:47.610 See you in the next lecture.